I'm getting this error:
[E] Ext.data.Session.checkModelType(): Unable to use anonymous models
in a Session
when trying to use a Session when binding a Grid with a Store via ViewModel:
ViewModel:
Ext.define('App.view.gridViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.gridview',
stores:{
gridstore: {
model: 'gridView',
autoLoad: true,
//This triggers the Exception:
session: true,
listeners: {
beforeload: function(store, operation, eOpts) {
var oProxy = this.getProxy();
oProxy.setExtraParams({
tableName: 'dbo.SomeTable'
, identityKey: "id"
, primaryKey: ["id"]
, mode: "readonly"
, lang: "es"
, output: 'json'
});
}
}
}
}
});
View:
Ext.define('App.view.gridView', {
extend: 'Ext.form.Panel',
//...
viewModel: {
type: 'gridview'
},
controller: 'gridview',
// Create a session for this view
session:true,
items: [{
xtype: 'grid',
reference: 'myGrid',
bind: '{gridstore}',
columns: [
//...
]
}]
//...
});
Model's data is fetch through a Proxy:
Model:
Ext.define("App.model.gridView", {
extend: 'Ext.data.Model',
schema: {
namespace: 'App.model'
},
proxy: {
//proxy remote api stuff......
}.
idProperty: 'id'.
primaryKeys: 'id'.
fields: [
//fields
]
});
I have no idea what an anonymous model is and I haven't found anything related in the web, any ideas?
Thanks in advance!
The reason seems to be that in my Server's response I have a JSON Object called "metaData", which collides with the one available in JSON Reader:
Response MetaData
The server can return metadata in its response, in addition to the
record data, that describe attributes of the data set itself or are
used to reconfigure the Reader. To pass metadata in the response you
simply add a metaData attribute to the root of the response data. The
metaData attribute can contain anything, but supports a specific set
of properties that are handled by the Reader if they are present:
http://docs.sencha.com/extjs/5.0/apidocs/#!/api/Ext.data.reader.Json
The curious thing is that I don't use any of the available metaData options for JSON Reader, nothing related to any anonymous model, therefore this might be considered a bug
Related
I am attempting to develop a Mobile app using Kendo Mobile's MVVM and JayData Data Access Library. I have run into an issue that I have worked on for about a week now with no luck. I am looking for a simple example consisting of Kendo two way binding using a model that is created by JayData's (asKendoDataSource) having an inverseProperty navigation property. I am not sure that JayData kendo.js Module supports models containing inverseProperty and in the process of testing, even after getting the data to save with the relationship, retrieval of the same record does not pull the relational data back into the viewmodel.
Can anyone provided a simple example of Saving and Retrieving such a model using the webSql provider?
Any help is greatly appreciated.
JayData Models (simplified):
//Expense Category Model
$data.Entity.extend('data.types.ExpenseCategory', {
Id: { type: 'Edm.Guid', key: true },
CategoryName: { type: 'string', required: true, minLength: 3, maxLength: 26 },
Expenses: { type: Array, elementType: "data.types.Expense", inverseProperty: "Category" }
});
//Expense Model
$data.Entity.extend('data.types.Expense', {
Id: { type: 'Edm.Guid', key: true },
ExpenseDescription: { type: 'string', required: true },
Category: { type: "data.types.ExpenseCategory", inverseProperty: "Expenses" }
});
// Entity Context
$data.EntityContext.extend('data.types.DbContext',
{
ExpenseCategories: { type: $data.EntitySet, elementType: data.types.ExpenseCategory },
Expenses: { type: $data.EntitySet, elementType: data.types.Expense },
});
// Database Context
data.context = new data.types.DbContext({ name: 'sqLite', databaseName: 'cDb' });
Kendo Viewmodel (simplified):
views.expenseCategoryPicker = kendo.observable({
app: null,
categories: db.context.ExpenseCategories.asKendoDataSource(),
expense: null,
itemClick: function(sender) {
var expense = views.expenseCategoryPicker.expense;
expense.set('Category', sender.data);
...add/update logic
expense.sync();
},
loadExpense: function(dataItem) {
views.expenseCategoryPicker.set('expense', undefined);
views.expenseCategoryPicker.set('expense', dataItem);
},
});
EDIT
I figured out why the data won't save and a work around. There is a bug in JayData's kendo.js module when using the Kendo MMVM binding and inverseProperty relationships. They(JayData) simply don't support their own Attach method when an object relationship is being set through their Kendo module. Therefor when you call Kendo's SET on the model passing in the related Object the Entity state on the Object being passed in is set to 20 (New) and JayData tries to create a new record and in my case failing due to primary key conflict. The Attach method sets the Entity state to unmodified.
I know there is probably a more elegant way to fix this in JayData's code, but for me simply adding the following line right before I use the Kendo set method to set the object relationship allows the record to be saved without error.
itemClick: function(sender) {
var expense = views.expenseCategoryPicker.expense;
//manually set the state so SQL won't try to create a new record
sender.data.innerInstance()._entityState = 10;
expense.set('Category', sender.data);
...
Subsequent reads require the Include('model') method to load the relational data as mentioned by Robesz (THANK YOU)
It would be nice to see JayData fix the data save issue in their Kendo module.
JayData doesn't load the related entities by default, you have to use the include() operator:
data.context.Expenses.include('Category').toArray(...)
The parameter of the include should be the name of the navigation property.
In Backbone.js, one can instantiate a model with pre-existing JSON data by using
var user = new Backbone.Model({ name: "John Doe", age: 30 });
And then perform updates with a single call
user.save({ age: 31 }, { success: successCallback, error: errorCallback });
This comes handy in all sorts of scenarios, such as when that data is already available on the client through caching or pre-populated templates (like using <%= raw #user.to_json %> in rails erb templates).
I'm curious to know how this is done when using $resource with Angular.js. Right now, I have a situation where my data is cached on the client before the $resource is created, and I'd like to update it without making an extra GET call to populate the object:
app.factory('User', ['$resource', function($resource) {
return $resource('/users/:user_id.json', { user_id: '#id' }, {
get: { method: 'GET' },
save: { method: 'PUT' },
create: { method: 'POST' },
destroy: { method: 'DELETE' }
});
}]);
And somewhere in my controller I'd like to just update an existing user without fetching it from the server:
app.controller('UsersController', ['User', function(User) {
// somehow initialize a user from an existing
// object, say { name: "John Doe", age: 30 }
user.age = 31
user.$save()
// instead of doing this
User.get({ user_id: 100 }, function(user, respHeaders) {
user.age = 31
user.$save()
});
}]);
I'm probably still in the Backbone mindset, but I'm really curious if I'm approaching this all wrong. Thanks.
$resource gives the option to create a new user like you would with any object:
var user = new User({name : 'John Doe', age: 30});
user.age = 32;
user.$save();
Resource Docs
so here is the problem, I use MVC and I have several stores that I declared on app.js.
But now I need to do a login validation, and only load the stores after I get the response from the server, but if leave the declaration in app.js when the app loads it automatically loads all the stores.
Here is what my app is going needs to do:
LoginView make the validation, if validation is successful it changes the view to ListView, this view has a list that loads data from a store and this view can create other views with other lists.
I tried to require the stores in the ListView, but it throws errors cannot call method getCount of null.
What can I do to make it work. Thanks for the help.
Here is some code:
Ext.define("App.view.Listview", {
extend: 'Ext.Container',
xtype: 'listview',
requires: ['App.view.Listviewdetails',
'App.view.Filtros.FiltroJanelaPrincipal.Janelafiltrotiempoview',
'App.view.Menuview',
'App.view.Resultadopesquisaview',
'App.view.Pesquisaview',
'App.view.Maisinfousuarioview',
'Ext.Label',
'Ext.field.Search',
'App.store.Tiempos',
'App.store.Empresas',
'App.store.Produtos',
'App.store.Usuarios',
'App.store.FiltrosEvento',
'App.store.Historicos',
'App.store.Pesquisas'
],
config: {
id: 'listView',
layout: 'card',
items: {
layout: 'vbox',
id: 'listaEventos',
items: [
{
xtype: 'list',
id: 'listaTiempos',
flex: 6,
emptyText: 'Empty',
store: 'Tiempos',
itemTpl: '{dataTermino} {descricaoPrevia}'
}
]
}
and one of the stores:
Ext.define("App.store.Tiempos",{
extend: 'Ext.data.Store',
config: {
model: 'App.model.Tiempo',
autoLoad: true,
proxy: 'searchProxy'
}
});
You can add the stores in require in the respective view classes. It is not compulsory to add in app.js.
So after login when the view will be instantiated the store will be loaded automatically.
I wanna get JSON from the server.And here is the django server view function:
def showChart(request):
data = [{"id":1, "name":"Tom", "email":"a#a.com"}, {"id":2, "name":"Bosh", "email":"c#c.com"}]
return HttpResponse(json.dumps(data), mimetype="application/json");
Obviously, showChart() will return a json.
My frontend extjs4 code:
Ext.onReady(function() {
Ext.define('ProductionInfo', {
extend: 'Ext.data.Model',
fields: ['email', 'id', 'name']
});
var store_new = Ext.create('Ext.data.Store', {
model: 'ProductionInfo',
proxy: {
type: 'ajax',
url : 'http://localhost:8000/production_data',
reader: {
type: 'json'
}
}
});
store_new.load();
alert(store_new.getCount());
});
But the alert dialog shows '0', while the right answer is '2'. So why I can't get JSON from server? (I can get the right JSON through a GET request in Chorme and Firefox)
You could check my sample: https://github.com/lucassus/extjs4-account-manager
It's rails application but json mechanism is very similar.
Basically you have to define a model with valid proxy: https://github.com/lucassus/extjs4-account-manager/blob/master/app/assets/javascripts/app/model/User.js
and a store which will have model attribute: https://github.com/lucassus/extjs4-account-manager/blob/master/app/assets/javascripts/app/store/Users.js
I am learning about Sencha so i have very basilar question.
I am trying to build a simple mvc application, with controller, views model and store.
I have this nmodel
Ext.define('rpc.model.Studenti', {
Extend: 'Ext.data.Model',
fields: [
{ name: 'cognome', type: 'string' },
{ name: 'previsione', type: 'string' }
]
});
this store (with inline data)
Ext.define('rpc.store.Studenti', {
model: 'rpc.model.Studenti',
storeId: 'gruppoStore',
autoLoad: true,
data: [
{cognome: 'uno', previsione: 'aaa'},
{cognome: 'due', previsione: 'bbb'},
{cognome: 'tre', previsione: 'ccc'}
]
});
the controller
Ext.define('rpc.controller.Home', {
extend: 'Ext.app.Controller',
stores: ['Studenti'],
models: ['Studenti'],
views: ['home.Fila','home.Griglia','home.Previsio'],
store: 'gruppoStore',
init: function() {
this.control({
'griglia button': {
tap: this.faqualcosa
}
});
},
faqualcosa: function(button){
...
var gruppoStoreMgr=this.getStudentiStore();
alert (gruppoStoreMgr.count());
for (var key in gruppoStoreMgr) {
//alert (key);
}
alert (gruppoStoreMgr.storeId);
alert (gruppoStoreMgr.isInstance);
//alert (gruppoStoreMgr.data);
alert (gruppoStoreMgr.autoLoad);
for (var key in gruppoStoreMgr.data[0]) {
//alert ("0"+key);
}
for (var key in gruppoStoreMgr.data[1]) {
//alert ("1"+key);
}
}
});
Please, what is the right way to access in function faqualcosa to the store data?
I've been able to have something like an instance (sure it is very near...) of the model with var gruppoStoreMgr=this.getStudentiStore(); but i have no trace of the data i've written in the store ("uno", "due"....). How to get that data? How to have in a controller funcion an object who refers to the real data in the store?
this.getStudentiStore().data.items
That is the most direct way to get to the data. It returns an array of the model records. If that's what you're looking for.
for(var i = 0; i < this.geStudentiStore().getCount(); i++ ) {
var record = this.getStudentiStore().getAt(i)
console.log(record.get('cognome'));
}
That should print out all the "cognomes"