How can I handle Extjs store Exceptions? - extjs

I am using Extjs 6.5.3 classic toolkit. I am having store for grid. I want to handle store load exceptions. How can I handle this?
My store is like this:
Ext.define('RUI.store.ProjectListStore', {
extend: 'Ext.data.Store',
sortOnLoad: false,
pageSize:RUIRamboConstants.DEFAULT_PAGE_SIZE,
proxy : {
type : 'ajax',
actionMethods: {
read: 'POST'
},
url: 'api.do',
reader: {
rootProperty: 'List',
type: 'json',
isURLConvert : true,
totalProperty: 'TotalRecords',
}
}
});
I get following response from server:
{
"limit": 10,
"page": 1,
"start": 0,
"TotalRecords": 2,
"userFilterId": 0,
"List": [
{
"id": 1,
"name" : "abc"
},
{
"id": 1926722,
"name" : "xyz"
}
]
}
When failure:
{
"returnCode": 1,
"messageKey": null,
"detailedMessage": null,
"exception": null,
"browser": "Mozilla 5.0 (Windows)",
"customParams": null,
"errorMessages": [
{
"messageKey": "duplicate",
"detailedMessage": "Duplicate."
}
],
"success": false
}
I want to catch this failure and want to show message as "Duplicate".
Please help!!
Thank you in advance.

You can listen to your store's load event, and then check if the response was successful or not, something like this:
listeners: {
load: function(store, records, success) {
if (!success) {
Ext.Msg.show({
title: 'Error',
message: recs[0].data.errorMessages[0].detailedMessage
})
}
}
}
Working Fiddle

Related

How to parse Json Two-dimensional array in Extjs 6.5.2?

I want to get all values in a Two-dimensional array and I'm sure I'm doing something in my model config. How can I do that?
Here's the code for my store:
Ext.define('Test.store.PathStore', {
extend: 'Ext.data.Store',
alias: 'store.PathStore',
storeId:'PathStore',
model : 'Test.model.PathModel',
autoSync:true,
proxy: {
type: 'ajax',
url:"url",
method:'GET',
reader: {
type: 'json',
rootProperty : ''
}
}
});
Here's the code for my model:
Ext.define('Test.model.PathModel', {
extend: 'Ext.data.Model',
fields: [
{name:'CID', type:'auto'},
{name:'NAME', type:'auto'},
{name:'DEFAULT_NAME', type:'auto'},
{name:'REPRESENTATIONS', type:'auto'}
]
});
Here's the code for my controller:
onButtonClick: function (selModel, record, index, options) {
var pathStore = Ext.getStore('PathStore');
pathStore.load({
// Some params,
callback: function(records, success, response, options) {
if(success){
var arr = Object.values(records[0].getData().DEFAULT_NAME);
console.log(records);
console.log(arr);
console.log(records[0].getData());
//Something I Have To Do
}
}
scope: this
});
}
Here's the format for my Json:
[
[
{
"CID": 111111,
"NAME": null,
"DEFAULT_NAME": "Hello guys",
"REPRESENTATIONS": null,
"ALL_REPRESENTATIONS": [
{
"cid": 111111,
"Name": "Hello",
"DefaultName": "guys",
}
]
}
],
[
{
"CID": 2222222,
"NAME": null,
"DEFAULT_NAME": "Hello World",
"REPRESENTATIONS": null,
"ALL_REPRESENTATIONS": [
{
"cid": 22222222,
"Name": "Hello",
"DefaultName": "World",
}
]
}
]
]
Json Format
I get [object Object] or something else in DEFAULT_NAME, NAME and CID. How can I do for this?
Thanks in advance,
Ben
One way to get the data from the nested array is to use the reader's transform configuration.
It is passed the raw (deserialized) data object. The transform
function returns a data object, which can be a modified version of the
original data object, or a completely new data object.
reader: {
type: 'json',
rootProperty: '',
transform: function(data) {
return Ext.Array.map(data, function(nestedDataArray) {
return nestedDataArray[0];
});
}
}
This way you get rid of the enclosing array and normalize the data.
Here is a working fiddle: https://fiddle.sencha.com/#view/editor&fiddle/25ut
If you have One-To-Many relaition in your model, use 'hasMany' property in model config:
Ext.define("Test.model.RepresentationModel", {
extend: 'Ext.data.Model',
fields: [
'cid', 'Name', 'DefaultName'
],
belongsTo: 'Test.model.PathModel'
});
Ext.define('Test.model.PathModel', {
extend: 'Ext.data.Model',
fields: [
{name:'CID', type:'auto'},
{name:'NAME', type:'auto'},
{name:'DEFAULT_NAME', type:'auto'},
{name:'REPRESENTATIONS', type:'auto'}
],
hasMany: {model: 'Test.model.RepresentationModel', name: 'ALL_REPRESENTATIONS'},
});

Loading nested GeoJson to FeatureStore with hasMany. Possible?

Is it possible to use associations while loading nested GeoJson to FeatureStore via vectorLayer?
Ext.define('Employee', {
extend: 'Ext.data.Model',
proxy: {
type: 'memory',
reader: {
type: 'json',
idProperty: 'id'
}
},
fields: [ { name: 'name', type: 'string' } ]
});
Ext.define('Company', {
extend: 'Ext.data.Model',
proxy: {
type: 'memory',
reader: {
type: 'json',
idProperty: 'id'
}
},
fields: [ { name: 'name', type: 'string' } ],
hasMany: { model: 'Employee', name: 'employees' }
});
var jsonData = {
companies: [
{
name: 'Foo',
employees: [
{ name: 'Jack' },
{ name: 'Joe' }
]
},
{
name: 'Bar',
employees: [
{ name: 'Jim' }
]
}
]
};
Ext.define('CompaniesExt', {
extend: 'Ext.data.Store',
model: 'Company',
data: jsonData,
storeId: 'CompaniesExt',
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'companies'
}
}
});
Ext.define('CompaniesGeoExt', {
extend: 'GeoExt.data.FeatureStore',
model: 'Company',
storeId: 'CompaniesGeoExt'
});
// data from json
var jsonStore = Ext.create('CompaniesExt');
// data from geoJson
var map = new OpenLayers.Map({ allOverlays: true });
var geoJsonStore = Ext.create('CompaniesGeoExt');
var layer = new OpenLayers.Layer.Vector('Companies', {
storeName: 'CompaniesGeoExt',
strategies: [
new OpenLayers.Strategy.Fixed(),
],
protocol: new OpenLayers.Protocol.HTTP({
url: "/companies.geojson",
format: new OpenLayers.Format.GeoJSON(),
})
});
map.addLayers([layer]);
geoJsonStore.bind(layer);
So, the first jsonStore works as expected, the employeesStore gets populated for each company. The second geoJsonStore does not. Employees data remain in raw.data and the sub-stores don't ge populated on load.
Is it supposed to work this way, or am I missing something?
Here's the contents of companies.geojson:
{
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "point",
"coordinates": [ 0, 0 ]
},
"type": "feature",
"properties": {
"name": "Foo",
"employees": [
{ "name": "Jack" },
{ "name": "Joe" }
]
}
},
{
"geometry": {
"type": "point",
"coordinates": [ 1, 1 ]
},
"type": "feature",
"properties": {
"name": "Bar",
"employees": [
{ "name": "Jim" }
]
}
}
]
}
It seems, that the easiest way is to rewrite data after loading features, for example on "featuresadded" event:
rewriteEmployees: function(event){
// which store
var store = event.features[0].layer.store;
// for each item do the rewrite
store.each(
function(r){
if (r.raw.data.emplyees)
r.raw.data.employees.forEach(function(e){
r.employees().add(e);
});
r.employees().commitChanges();
}
);
},

Sencha Touch. NestedList move, insert, remove items

My question is about how to move, insert and remove items in NestedList
I have a NestedList like this:
// MODEL
Ext.define('MyApp.model.Comments', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'text', type: 'string'}
]
}
});
// NESTEDLIST
Ext.define('MyApp.view.Comments', {
requires: [
'Ext.data.TreeStore'
],
config: {
id: 'comments',
store: {
type: 'tree',
root: {},
model: 'MyApp.model.Comments',
proxy: {
type: 'ajax',
actionMethods: {read: 'POST'},
url: './comments.php',
timeout: 4000,
enablePagingParams: false,
extraParams: {
action: 'get-comments'
}
}
},
displayField: 'text',
detailCard: {
xtype: 'container',
layout: 'vbox',
items: [
{
id: 'comment-text-field',
flex: 1
}
]
},
listeners: {
leafitemtap: function(el, list, index, target, record) {
var detailCard = el.getDetailCard(),
text = record.data.text,
commentField = detailCard.query("#comment-text-field");
var textHtml = '<b>text: </b>' + text;
if (commentField) {
commentField[0].setHtml(textHtml);
}
},
destroy: function(el) {
el.getDetailCard().destroy();
}
}
}
});
// './comments.php' response
[
{
"text": "New comments",
"children": [
{
"text": "NestedList provides a miller column interface to navigate between",
"leaf": true
},
{
"text": "The absolute bottom position of this Component; must be a valid CSS length value",
"leaf": true
}
]
},
{
"text": "Checked comments",
"children": [
{
"text": "Whether or not this Component is absolutely centered inside its Container",
"leaf": true
},
{
"text": "Component is absolutely centered inside its Container",
"leaf": true
},
{
"text": "More comments",
"leaf": true
}
]
}
]
It works fine but i need to move, remove and add items in NestedList.
F.e. when i open one of "New comments" (leaf item is opened and leafitemtap fired), opened item should be removed from "New comments" and inserted into "Checked comments".
I see 2 ways to do it:
Send request to update comments.php response AND update store via Sencha functionality
Send request to update comments.php response AND reload comments.php each time when some items are clicked to update NestedList
Of course 1st way is better, but I have no idea how to do at least one of them.
Hope you will help me, thsnk's!
Well, looks like there is no convenient way to do that. Here is comment on official forum:
http://www.sencha.com/forum/showthread.php?205097-How-to-create-a-Nested-List-with-dynamic-loading-of-each-node

The URL of an ajax proxy - Ext JS

I have a couple of questions about the url field of an ajax proxy, and Ext.Ajax.request
I'm getting a JSON response from an Ext.Ajax.request, and sending that data to a store. (I'm also trying to use the pagingToolbar, which is highly uncooperative at the moment)
Anyhow, the paging only seems to slightly work when I use an ajax proxy, however I'm not sure what to put in as the URL. Currently it's url: ''
var store = Ext.create('Ext.data.Store', {
storeId : 'resultsetstore',
autoLoad : false,
pageSize : itemsPerPage,
fields: [
{name : 'id', type : 'auto'},
{name : 'name', type : 'auto'},
{name : 'description', type : 'auto'}
],
proxy: {
type : 'ajax',
url : '???',
reader: {
type : 'json',
root : 'elements'
}
}
});
It seems the url reads data from a .json file in a specific directory (i.e. url: 'myData/data.json'), but there isn't any file like that to read from, as my response is coming back as a JSON Object.
And here is my request/response, which I parse and send to my store:
var request = Ext.Ajax.request({
url : 'MCApp', //here I specify the Servlet to be read from
jsonData : searchquery, //A JSON Object
params:{
start:0,
limit: itemsPerPage
},
success : function(response) {
mainresponse = response.responseText;
//etc.
}
Is having a separate request redundant?
Could I accomplish this within my store alone (passing my searchquery as a parameter to the server and all that jazz)?
I apologize for this jumbled question in advance!
Cheers
You can use a memory proxy and set the store data with the data property, but I don't recommend that.
If I where you I would forget the ajax request and start take advantage of the store's proxy.
Here's an example
var store = Ext.create('Ext.data.Store', {
storeId: 'resultsetstore',
autoLoad: false,
pageSize: 20,
fields: ['id','name','description'],
proxy: {
type: 'ajax',
url: 'urlToTheServlet', //here I specify the Servlet to be read from
extraParams: {
searchquery: 'Test'
}, //A String Object
reader: {
type: 'json',
root: 'elements'
}
}
});
store.load();
note that the start, limit are dealt with in the background. You don't have to set them manually. You can set a pageSize but it has it's own default, so it's not required.
This is what your data is expected to look like:
{
"elements": [
{
"id": 1,
"name": "John",
"description": "Project Manager"
},
{
"id": 2,
"name": "Marie",
"description": "Developer"
},
{
"id": 3,
"name": "Tom",
"description": "Technical Lead"
}
]
}
UPDATE: Passing an object as payload to the proxy
I had the same issue and I couldn't find an out of the box solution so I wrote my own proxy to resolve this.
Ext.define('BCS.data.proxy.AjaxWithPayload', {
extend: 'Ext.data.proxy.Ajax' ,
alias: 'proxy.ajaxwithpayload',
actionMethods: {
create: "POST",
destroy: "POST",
read: "POST",
update: "POST"
},
buildRequest: function(operation) {
var me = this,
request = me.callParent([operation]);
request.jsonData = me.jsonData;
return request;
}
});
Now you can do this:
var store = Ext.create('Ext.data.Store', {
storeId: 'resultsetstore',
autoLoad: false,
pageSize: 20,
fields: ['id','name','description'],
proxy: {
type: 'ajaxwithpayload',
url: 'urlToTheServlet', //here I specify the Servlet to be read from
jsonData : YOUR_OBJECT
reader: {
type: 'json',
root: 'elements'
}
}
});
I prefer to keep each method in a separated endpoint:
proxy: {
type: 'ajax',
reader: {
type: 'json'
},
api: {
read: 'getCenarioTreeNode', // To request a node children (expand a node)
create: 'createCenarioTreeNode', // When you insert a node
update: 'updateCenarioTreeNode', // When you change a node attribute
destroy: 'destroyCenarioTreeNode' // When you delete a node
},
writer: {
type:'json',
encode:true,
rootProperty:'data'
}
},

How to load the tree panel tree store with Ajax response

How to load the tree panel tree store with Ajax response.
How to load the tree panel tree store with Ajax response json.
i can load it locally , i.e. if i have the json file locally available then i can load it through configured proxy by using treeStore.load() method.
But now if i have the data from a Ajax response then how can i do that?
Model :
Ext.define('dimExpModel', {
extend : 'Ext.data.Model',
fields : [
{
name: 'memberName'
},
{
name: 'memberCode'
},
{
name: 'dimension'
}
]
});
Store :
var dimExpStore = Ext.create('Ext.data.TreeStore',{
storeId:'dimExpStore',
model:dimExpModel,
proxy: {
type: 'memory',
reader: {
type: 'json'
}
}
});
Tree Panel :
{
"xtype": "treepanel",
"height": 250,
"id": "treePanel",
"width":400,
"title":"My Tree Panel",
"store": "dimExpStore",
"displayField":"memberName",
"useArrows":true,
"viewConfig": {
}
};
Any help is appreciated.
T would do it like this:
{
"xtype": "treepanel",
"height": 250,
"id": "treePanel",
"width":400,
"title":"My Tree Panel",
"rootVisible":false,
"store":{autoLoad:true,"fields":[{"name":"id",type:"string"},
{"name":"memberName","type":"string"},{"name":"memberCode","type":"string"},
{"name":"memberCode","type":"dimension"}],
proxy:{type:'ajax',url:'json.php'},root:{text:"Members","id":"src","expanded":true}}
"displayField":"memberName",
"useArrows":true,
"viewConfig": {
}
};
In my example json.php returs the desired json in a correct form.
Edit
Take a look at "id" param inside root block. Each time when you click on tree nodes containing children, at the server side you should form a correct response depending on that "id" which is actually id_parent of all those children nodes.
You need to define your store proxy as ajax and call store.load()
var dimExpStore = Ext.create('Ext.data.TreeStore',{
storeId:'dimExpStore',
model:dimExpModel,
proxy: {
type: 'ajax',
url : 'users.json',
reader: {
type: 'json',
root: 'records',
totalProperty: 'recordCount',
successProperty: 'success'
}
}
});

Resources