ExtJS store initialization using json fails - javascript

I have a store like this:
Ext.define('app.store.System', {
extend : 'Ext.data.Store',
model : 'app.model.System',
autoLoad: true,
autoSync: true,
proxy: {
type: 'rest',
format: 'json',
url: '/application/appinfo',
method : "GET",
reader: {
type: 'json',
root: 'System'
},
writer: {
root: 'System',
allowSingle: false
}
}
});
and I have a service endpoint to handle requests that match /application with this method:
#GET
#Path("/{sysinfo}")
public List<SystemInfo> getSystemInfo() {
if(sysinfo == null){
sysinfo = new SystemInfo();
...initialize
}
List<SystemInfo> resultList = new ArrayList<SystemInfo>();
resultList.add(sysinfo);
return resultList;
}
and it seemed to work... when I tried to to reach localhost:port/application/sysinfo.json I got this:
{ [{"address":"...","feeds":["feed1","feed2"] } ] }
which seems correct but when I try to read the data from the store in the view's init method:
var store = Ext.StoreManager.lookup('System');
var data = [];
store.each(function(record) {
data.push(record.getData());
console.log("record data: ");
console.log(record.getData());
});
console.log(data[0]);
It says that it's undefined as if the store was empty. I tried it with the debugger and i found that the getSystemInfo() was called after the view's initcomponent but unfortunately I don't know why that is or how to solve it. Any ideas?
Thanks for your time.

Have you tried loading your store first?
var store = Ext.StoreManager.lookup('System');
var data = [];
store.load({
callback: function(storeVar, records, successful) {
Ext.each(records, function(record) {
data.push(record.getData());
console.log("record data: ");
console.log(record.getData());
});
}
console.log(data[0]);
});
And what boris says is true, you need to define your root property in the returned JSON.
If you're using chrome or firefox you can also check which network call is made, and what it returns (JSON data...).

Try this:
return new { success: true, System = resultList};

Related

Loading js-grid then filtering data

I have data being pulled from a db using php and then passed into javascript to load js-grid. I also have a dropdown populated with php containing the default value selected and stored by the user. My goal is to populate the grid with all data returned, then filter it based on the selected option in the dropdown.
I can't seem to understand how to load then filter data using js-grid.
<script type="text/javascript">var order_json = <?= $order_json ?>; var user_list = <?= $user_list['activeListId'] ?>;</script>
<script type="text/javascript" src="js/main.js"></script>
main.js
$( document ).ready(function() {
$("#jsGrid").jsGrid({
width: "100%",
height: "400px",
inserting: false,
editing: false,
sorting: true,
paging: false,
pageSize: 30,
noDataContent: "No orders found",
data: order_json,
fields: [
{ name: "OrderId", type: "number", title: "Order ID", visible: false },
{ name: "ListId", type: "number", title: "Order List ID", visible: true},
{ name: "Name", type: "text", title: "Order Name", align: "left"}
],
});
var grid = $("#jsGrid").data("JSGrid");
grid.search({ListId: user_list})
});
I have tried some different approaches and none have worked. Any help would be appreciated.
With js-grid the actual filtering of the data should be implemented by developer.
The filtering could be done on the client-side or server-side. Client-side filtering implemented in loadData method of controller. Server-side filtering is done by a server script that receives filtering parameters, and uses them to retrieve data.
Here is how your controller.loadData method could look like:
loadData: function(filter) {
var d = $.Deferred();
// server-side filtering
$.ajax({
type: "GET",
url: "/items",
data: filter,
dataType: "json"
}).done(function(result) {
// client-side filtering
result = $.grep(result, function(item) {
return item.SomeField === filter.SomeField;
});
d.resolve(result);
})
return d.promise();
}
As for data option, it's used only for static grid data.
Worth to mention that it would be better to provide data to grid with a REST-y service (of course, it can be done with PHP).
Here is the sample project showing how to use js-grid with a REST service on PHP https://github.com/tabalinas/jsgrid-php.
loadData: function (filter) {
criteria = filter;
var data = $.Deferred();
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: "/api/advertisements",
dataType: "json"
}).done(function(response){
var res = [];
if(criteria.Title !== "")
{
response.forEach(function(element) {
if(element.Title.indexOf(criteria.Title) > -1){
res.push(element);
response = res;
}
}, this);
}
else res = response;
if(criteria.Content !== "")
{
res= [];
response.forEach(function(element) {
if(element.Content.indexOf(criteria.Content) > -1)
res.push(element);
}, this);
}
else res = response;
data.resolve(res);
});
return data.promise();
},
Whenever filtering is involved the function loadData of the controller is called.
There you can implement the filtering functionality that you want.
Here is an example of a generic filter that checks if the string you 've typed in the filter row is contained in your corresponding rows, works with numbers and other types as well
loadData: function (filter) {
return $.get('your.url.here')
.then(result => result.filter(row => Object.keys(filter).every(col =>
filter[col] === undefined
|| ('' + filter[col]).trim() === ''
|| ('' + row[col]).toLowerCase().includes(('' + filter[col]).trim().toLowerCase())
)))
}
If you're not getting your data from a server you can still use the loadData function as described here: https://github.com/tabalinas/jsgrid/issues/759
If you want to invoke filtering manually you can use the search function as described in the docs: http://js-grid.com/docs/#searchfilter-promise

HTTP DELETE request without body

I am facing the same problem as mentioned here: I am trying to connect my ExtJS 4.1 store with REST API, but when I delete the record from the store and consequently invoke HTTP DELETE method, it gets rejected by the server-side because the HTTP request that ExtJS sent contains body. Unfortunately, the accepted answer on the link above is not valid for version 4 of ExtJS and higher.
The best that I achieved so far is to send empty array (literally, [] ) as a body, but of course this is still rejected:
This is my code:
Ext.define('TT.proxy.CustomRestProxy', {
alias: 'proxy.customrestproxy',
extend: 'Ext.data.proxy.Rest',
buildRequest: function(operation) {
var request = this.callParent(arguments);
if(operation.action === 'destroy')
{
delete request.operation.records;
}
return request;
}
});
defineStore = function(storeName, modelName, url) {
var storeProperties = {
extend: 'Ext.data.Store',
requires: modelName,
model: modelName,
id: storeName,
proxy: {
type: 'customrestproxy',
url: url,
batchActions: false,
noCache: false,
headers: { 'Content-Type': 'application/json' },
reader: {
type : 'json',
totalProperty: 'total',
successProperty: 'success',
root: 'data'
},
writer: {
type : 'json'
},
}
};
Ext.define(storeName, storeProperties);
};
I would accept any answer that solves this issue, it does not have to include ExtJS-specific features, i.e. intercepting AJAX request or similar technique is also welcome.
There is a workaround based on AJAX interceptor, inspired by this link. This code solves the problem regardless of the framework used, so it can be also useful for other people who are not necessarily using Ext JS:
(function(XHR) {
"use strict";
var open = XHR.prototype.open;
var send = XHR.prototype.send;
var httpMethod;
XHR.prototype.open = function(method, url, async, user, pass) {
httpMethod = method;
this._url = url;
open.call(this, method, url, async, user, pass);
};
XHR.prototype.send = function(data) {
if(httpMethod === 'DELETE')
{
data = null;
}
send.call(this, data);
}
})(XMLHttpRequest);

Persist additional dataSource.read parameters on paganation in Kendo data grid

I have a Kendo Grid that loads data via ajax with a call to server-side ASP.NET read method:
public virtual JsonResult Read(DataSourceRequest request, string anotherParam)
In my client-side JS, I trigger a read when a button is clicked:
grid.dataSource.read( { anotherParam: 'foo' });
grid.refresh();
This works as expected, only I lose the additional param when I move through the pages of results in the grid, or use the refresh icon on the grid to reload the data.
How do I persist the additional parameter data in the grid?
I have tried setting
grid.dataSource.data
directly, but without much luck. I either get an error if I pass an object, or no effect if I pass the name of a JS function that returns data.
if you want to pass additional parameters to Read ajax datasource method (server side), you may use
.DataSource(dataSource => dataSource
...
.Read(read => read.Action("Read", controllerName, new { anotherParam= "foo"}))
...
)
if you want to pass additional parameters through client scripting you may use datasource.transport.parameterMap, something as below
parameterMap: function(data, type) {
if (type == "read") {
return { request:kendo.stringify(data), anotherParam:"foo" }
}
Use the datasource.transport.parameterMap
parameterMap: function(data, type) {
if (type == "read") {
return kendo.stringify(data, anotherParam);
}
I'm not sure where your other param is coming from, but this is generally how I send extra parameters to the server.
http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-transport.parameterMap
if use datasource object :
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/Api/GetData',
contentType: "application/json; charset=utf-8", // optional
dataType: "json",
data: function () {
return {
additionalParam: value
};
}
},
//parameterMap: function (data, type) {
// and so use this property to send additional param
// return $.extend({ "additionalParam": value }, data);
//}
},
schema: {
type: "json",
data: function (data) {
return data.result;
},
},
pageSize: 5,
serverPaging: true,
serverSorting: true
});
and set options in grid:
$("#grid").kendoGrid({
autoBind: false,
dataSource: dataSource,
selectable: "multiple cell",
allowCopy: true,
columns: [
{ field: "productName" },
{ field: "category" }
]
});
and in click event this code :
dataSource.read();
and in api web method this action:
[HttpGet]
public HttpResponseMessage GetData([FromUri]KendoGridParams/* define class to get parameter from javascript*/ _param)
{
// use _param to filtering, paging and other actions
try
{
var result = Service.AllCustomers();
return Request.CreateResponse(HttpStatusCode.OK, new { result = result });
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.BadRequest, new { result = string.Empty });
}
}
good luck.
To persist the updated value of the additional parameter through pagination, you will need to create a global variable and save the value to it.
var anotherParamValue= "";//declare a global variable at the top. Can be assigned some default value as well instead of blank
Then, when you trigger the datasource read event, you should save the value to the global variable we created earlier.
anotherParamValue = 'foo';//save the new value to the global variable
grid.dataSource.read( { anotherParam: anotherParamValue });
grid.refresh();
Now, this is important. In your datasource object transport.read.data must be set to use a function as shown below:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/Api/GetData',
contentType: "application/json; charset=utf-8", // optional
dataType: "json",
//Must be set to use a function, to pass dynamic values of the parameter
data: function () {
return {
additionalParam: anotherParamValue //get the value from the global variable
};
}
},
},
schema: {
type: "json",
data: function (data) {
return data.result;
},
},
pageSize: 5,
serverPaging: true,
serverSorting: true
});
Now on every page button click, you should get the updated value of the anotherParam which is currently set to foo

Backbone.js Unable to parse response from collectio.toJSON()

I am learning Backbone and it would be great if someone can help me with this issue. After I do a fetch on my collection, in success callback I get the parsed data using collection.toJSON(), this actually returns an object and I am unable to get anything out of this object. This object actually has data that I need.
My question is how do I access rows property in my object. Here is my code for your reference
var testCollection = Backbone.Collection.extend({
model:myModel,
url: '/myApiEndPoint',
data: '',
initialize: function(models, options) {
this.data = models.data;
},
fetch: function(options) {
var ajaxConfig = {
url: this.url,
data: this.data,
type: 'POST',
dataType: 'text',
contentType: 'text/xml',
parse: true
};
options = _.extend({}, ajaxConfig, options);
return Backbone.Collection.prototype.fetch.call(this, options);
},
parse: function(xmlResponse) {
// I have some parsing logic to extract uid and rows from my xmlResponse
return {
uid: uid,
rows: rows
};
},
});
var collObj = new testCollection({data: xmlQuery1});
collObj.fetch({
success: function(collection){
// This code block will be triggered only after receiving the data.
console.log(collection.toJSON());
}
});
As the name toJSON suggests, it returns you the array of JSON objects where each object is a Model's JSON object. You can fetch the required properties in this way:
collObj.fetch({
success: function(collection){
// This code block will be triggered only after receiving the data.
console.log(collection.toJSON());
var uid = 'uid-of-an-object-to-access';
var rows = collection.get(uid).get('rows');
console.log(rows);
}
});

wijdatasource error

Is there a way to debug or get an error when wijdatasource complete is request with a wijhttpproxy and have some problems with the data?
data: new wijdatasource({
dynamic: true,
proxy: new wijhttpproxy({
url: "#Url.Action("List")",
type: "POST",
dataType: "json"
}),
reader: {
read: function (datasource) {
alert(datasource);
var count = datasource.data.TotalRowCount;
datasource.data = datasource.data.Items;
datasource.data.totalRows = count;
new wijarrayreader([
{ name: "CdCF", mapping: "CdCF" },
{ name: "Descrizione", mapping: "Descrizione" }
]).read(datasource);
}
}
})
With the internet explorer debugger I can see the call is made with a 200 HTTP response to the List action but "alert(datasource);" is never executed.
I want to get the error that make the datasource not parse the data (if this is the error).
In a standard ajax call I could have had an "error" callback to try to debug the problem.
$.ajax({
error: function (error) {
alert("error: " + error);
},
url: '#Url.Action("List")',
success: function (code) {
var myModel = {
items: eval(code)
};
}
});
I think you want to do a Get instead of a Post.
proxy: new wijhttpproxy({
url: "#Url.Action("List")",
type: "Get",
dataType: "json"
}),
What I did is that I caught the error in the controller an modified the object I was sending back to have a "success" boolean that I checked on the read function so that if datasource.data.success was true, then I would process the data if not I would spit out a message. You would have to put everything in your controller action inside a try-catch block.

Categories