ExtJS REST store: sync() doesn't remove records on the server - json

I use ExtJS 4.2.2. A store for browsing and managing folders is defined like this:
Ext.define('hds.store.CaseFolders', {
extend: 'Ext.data.Store',
requires: [
'app.model.Folder',
'Ext.data.proxy.Rest',
'Ext.data.reader.Json',
'Ext.data.writer.Json'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: false,
model: 'app.model.Folder',
storeId: 'Folders',
proxy: {
type: 'rest',
url: '/api/folders.json',
reader: {
type: 'json',
messageProperty: 'message',
root: 'data'
},
writer: {
type: 'json',
writeAllFields: false,
root: 'data'
}
}
}, cfg)]);
}
});
It uses this model:
Ext.define('app.model.Folder', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.Field'
],
fields: [
{
name: 'name',
type: 'string'
},
{
name: 'parentId',
type: 'int'
},
{
name: 'type',
type: 'string'
}
]
});
Folders can be added, renamed and removed.
When changing the name of the folder, for example and using store.sync(), the record is properly synced to the server with a PUT containing id and name attributes.
However, when deleting the folder, store.sync() doesn't send any request to the server. A callback function was added to sync, but it is not called at all.
It seems that the REST store (proxy?) "thinks" that there is nothing to sync to the server.
Why is it like that?

Found the reason for the problem that I had:
The store is filtered to show content of the folder to be deleted.
When wanting to delete current folder, its record is filtered away.
Adding a line to remove filters before removing the parent folder record solved the problem.

Related

JSON response with various data types

I have a JSON response like this
"{"total":1,"userBeanId":300,"list":[{"errors":[],"success":true,"liferayUserId":31503,"companyId":null,"groupId":null,"locale":null,"status":null,"liferayUserGroupId":null,"idProvider":null,"idClient":null,"userType":4,"userId":200,"email":"xpto#gmail.com","telefone":"999999999","nome":"MYNAME","role":"MY_ROLE","perfil":"Administrator","lastName":null}],"success":true}"
and what I have is a store that reads the list content, like this
"Ext.define('
MYPROJECT.store.Profiles', {
extend: 'Ext.data.Store',
model: 'MYPROJECT.model.Profile',
autoLoad: true,
pageSize: 10,
remoteSort: true,
remoteFilter: true,
proxy: {
type: 'ajax',
api: {
read: '/delegate/rlapi-common/profile/list'
},
enablePaging: true,
reader: {
type: 'json',
root: 'list',
successProperty: 'success'
}
}
});"
and the store "reads" the list successfully. However, I'd like to be able to access the "userBeanId" field as well. Is there any way I can access it by this store (by changing the root to something on an upper-level)? It confuses me as the store "maps" to a model and the userBeanId doesn't fit in the model.
Model:
Ext.define('MYPROJECT.model.Profile', {
extend: 'Ext.data.Model',
fields: [
'userId',
'nome',
'telefone',
'email',
'role',
'perfil'
],
});
You can access store.proxy.reader.rawData to get the most recently loaded JSON. As you suggested, it doesn't make sense being part of the model, but you can read extra meta info via the reader.

Extjs Json load without Root

My problem is the json I am getting doesn't have a root. I can get the store to load the URL and I get the JSON back but the store data is empty and nothing shows in the callback.
Json:
[
{
"symbol": "GM"
},
{
"symbol": "GA"
}
]
Model and Store:
Ext.define('Symbol', {
extend: 'Ext.data.Model',
fields: ['symbol']
});
Ext.define('Doc.store.symbol', {
extend: 'Ext.data.Store',
model: 'Symbol',
proxy: {
type: 'jsonp',
url: 'datasource/symbol',
reader: {
type: 'json',
model: 'symbol'
},
}
});
I tried removing the root as well but nothing came back in the store or the callback. My googlefu is turning up nothing good on json without root.
the root should be defined as blank root:''
Here is a code demonstrating the proper setup:
Ext.define('boomer', {
extend:'Ext.data.Model',
fields: ['symbol'],
proxy: {
type: "ajax",
url: "data.json",
extraParams: {
},
reader: {
type: "json",
root: "",
successProperty: "success"
}
}
});
var store = Ext.create('Ext.data.Store',{
model: 'boomer',
});
store.load({
callback:function(){
Ext.Msg.alert('Store Items', store.data.items.length);
console.log(store.data.items);
}
});
Here is a fiddle demonstrating working code.
extend Ext.data.reader.Json to adjust your response.Later use it inside proxy reader.
there is a answer here

Store data is empty though I have response from server

Here is my model:
Ext.define('DynTabBar.model.Menu',{
extend: 'Ext.data.Model',
config: {
fields: [{
name: 'Title', type: 'string'
}, {
name: 'Level', type: 'int'
}, {
name: 'Parent', type: 'string'
}]
}
});
Store:
Ext.define('DynTabBar.store.MenuItems', {
extend: 'Ext.data.Store',
xtype: 'menustore',
config: {
storeId: 'menuStore',
model: 'DynTabBar.model.Menu',
autoLoad: false,
proxy: {
type: 'ajax',
id: 'menuproxy',
url: 'http://localhost:50567/api/Menu',
reader: {
type: 'json'
}
}
}
});
In controller I have smth like that:
var mainStore = Ext.getStore('menuStore');
mainStore.load();
My json respone from server is:
[{"Title":"home","Level":1,"Parent":""},{"Title":"home1","Level":2,"Parent":"home"},{"Title":"home2","Level":2,"Parent":"home"},{"Title":"info","Level":1,"Parent":""},{"Title":"info1","Level":2,"Parent":"info"},{"Title":"info2","Level":2,"Parent":"info"},{"Title":"info3","Level":2,"Parent":"info"}]
But store data is empty. What I'm missing or doing wrong?
I fixed the problem, the problem is that I'm not waiting while store data is loaded and do something while store isn't loaded. I fix that doing what I need in store loaded callback.
mainStore.load(callback);

Sencha store and model set up for use with Json

I've got a Json file......
[
{
"Title":"Package1",
"id":"1",
"POI":[
{
"Title":"POI1",
"LayerID":"1",
},
{
"Title":"POI2",
"LayerID":"1",
}
},
{
"Title":"Package2",
"id":"2",
"POI":[
{
"Title":"POI3",
"LayerID":"2",
},
{
"Title":"POI4",
"LayerID":"2",
}
}
]
populating a store.....
Ext.define('Murmuration.store.MyPackages', {
extend: 'Ext.data.Store',
xtype: 'myPackages',
config: {
model: 'Murmuration.model.PackagesModel',
proxy: {
type: 'ajax',
url : 'data/store.json',
reader: {
type: 'json'
}
},
autoLoad: true
}
});
with a model......
Ext.define('Murmuration.model.PackagesModel', {
extend: 'Ext.data.Model',
xtype: 'packagesModel',
config: {
fields: [
{name: 'Title', type: 'string'},
{name: 'id', type: 'int'}
]
}
});
for said list......
Ext.define('Murmuration.view.homeList', {
extend: 'Ext.List',
xtype: 'homeList',
fulscreen: true,
config: {
title:'Murmuration',
itemTpl: '<div>{Title}</div>',
store:'MyPackages',
fulscreen: true,
}
});
The list Items are successfully being populated with 'Package1' and 'Package2'. But for the life of me I can't successfully change the code to populate the list with the POI titles for the fist package........'POI1' and 'POI2'. How would I go about successfully implementing the following? Any help would be greatly appreciated.
The json you've given is nested so things little different here. First thing is, you need to specify a rootProperty in your reader. So you define a root element in your json and that element will be set to rootProperty.
Next part is, you have POI as array of objects. So you'd need a separate model for POI.
Model for POI can be defined -
Ext.define('Murmuration.model.POIModel',{
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'Title', type: 'string'},
{name: 'LayerID', type: 'int'}
],
belongsTo:'Murmuration.model.PackagesModel'
}
});
After a close look, you'll notice there's one extra config belongsTo. This represents many to one association with your PackageModel since there are many POI in each package.
After doing this, you'd need to change you PackageModel also to -
Ext.define('Murmuration.model.PackagesModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'Title', type: 'string'},
{name: 'id', type: 'int'}
]
},
hasMany:{
associationKey:'POI',
model:'Murmuration.model.POIModel',
name:'POI'
}
});
here, hasMany represents that this model is having multiple model instances of POI model. associationKey is the key POI from you json and model gives the model instance of POI model.
After doing that you'd need to change your reader in store to -
Ext.define('Murmuration.store.MyPackages', {
extend: 'Ext.data.Store',
config: {
model: 'Murmuration.model.PackagesModel',
proxy: {
type: 'ajax',
url : 'data/store.json',
reader: {
type: 'json',
rootProperty:'items'
}
},
autoLoad: true
}
});
rootProperty should be set to root of you json. I assumed it could be items here.
Finally in you view you can have template set up like this -
itemTpl: new Ext.XTemplate(['<div>Package Title => {Title}'+
'<tpl for="POI"><h6>POI title => {Title}</h6><h6>POI layer => {LayerID}</h6></tpl></div>'
]),
2 things I found in your code are not correct though -
Store and Model can not have a xtype.
All the config options should be inside config:{} only.

EXTJS 4 Json nested data in grid panel

This topic has been discussed several times on the web but all subjects none helped me solve my problem.
My javascript code receives the JSON nested data. All JSON data Level 1 data are transcribed in the grid panel but all child data none.
I have tried so many ways but impossible.
That's why I'm asking you to help me please.
My JSON:
{
"success":true,
"error":false,
"redirectUrl":null,
"fund":[{
"cat_id":1,
"catname":"Europe OE Japan Large-Cap Equity",
"region":{
"region_id":2,
"region_name":"JAPAN"
}
},{
"cat_id":2,
"catname":"Europe OE Europe Large-Cap Growth Equity",
"region":{
"region_id":1,
"region_name":"EUROPE"
}
}]
}
MY model:
var Recommended = new function() {
this.DataModel = function() {
Ext.define('Fund', {
extend: 'Ext.data.Model',
fields: [{
name: 'catname',
type: 'string'
},{
name: 'cat_id',
type: 'int'
}],
proxy :{
type: 'rest',
url: application +'directory/function',
reader: {
type: 'json',
root: 'fund'
}
},
associations: [{
type: 'hasOne',
model: 'Region',
primaryKey: 'region_id',
name:'region'
}]
});
Ext.define('Region', {
extend: 'Ext.data.Model',
fields: [{
name: 'region_name',
type: 'string'
},{
name: 'region_id',
type: 'int'
}]
});
}
My Store & grid Panel:
this.JSONstore = function() {
var storeRecommended;
storeRecommended = Ext.create('Ext.data.Store', {
model: 'Fund',
autoLoad:true,
groupField: 'region_name'
});
var colModel =
[
{
text: 'REGION',
width: 200,
dataIndex: 'region_name',
name:'region_name',
mapping:'region.region_name'
},{
text: 'MORNINGSTAR',
width: 300,
dataIndex: 'catname',
name:'catname'
}
];
var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
groupHeaderTpl: 'Classe: {name} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})',
hideGroupedHeader: false
});
var grid = Ext.create('Ext.grid.Panel', {
renderTo: 'recommendedlists',
collapsible: true,
iconCls: 'icon-grid',
frame: true,
store: storeRecommended,
width: 1200,
height: 400,
title: 'Test',
resizable: true,
features: [groupingFeature],
columns: colModel,
fbar : ['->', {
text:'Clear Grouping',
iconCls: 'icon-clear-group',
handler : function(){
groupingFeature.disable();
}
}]
});
}
this.initControlsOnload = function() {
Recommended.DataModel();
Recommended.JSONstore();
}
} // close Recommended function
The problem is your store bound to the grid knows nothing about Regions. It stores Funds. So you can't ask for a column to map to a data property that's not in the store.
The store is flat list of Fund records. And sure an individual Fund itself might know about the Region it belongs to, but the store containing a list of funds does not.
What to do?
What needs to happen is flattening out of your data structure on the client side. Why? Because the grid is flat. If you had multiple regions per fund - then we would be talking about a different solution.
How to do that?
If you control the server side of this app then add a Region field to the Fund object, then your data set is simple, straight forward and more importantly flat. If you can't (or don't want to) change the server side, then you can change the client side Model mapping. Essentially you would change your Fund model to something like this:
Ext.define('Fund', {
extend: 'Ext.data.Model',
fields: [
{ name: 'catname', type: 'string' },
{ name: 'cat_id', type: 'int' },
{ name: 'region_name', type: 'string',
mapping: 'region.region_name'},
{ name: 'region_id', type: 'int',
mapping: 'region.region_id'}
]
....
});
You see what we did there? We flattened the Region data into the Fund record. And now your store will have no problems accessing Region name data by name.
Good Luck,
Dmitry.