Extjs 3.4 custom JSONReader - javascript

I haven't had a question from quite a while, but I finally ended up hitting a wall here. Anyways, to make this easy. I am trying to create a JSON store in extjs 3.4 (work related, and no I am not updating).
Well, I created the queries as usual with the proper response and fill it up. My problem is that I have 1 extra property on the JSON that I want to be able to pull and use on the app.
Sample of my JSON from the response object in chrome:
myInventory: [{Priority:1, PMNumber:444, Description:fix-a-tape, Assets:3, Storage_Count:0,…},…]
percent: 97.040498442368
totalCount: "3"
Now, I know this is correctly formatted because the Grid I am using gets populated, but I can't get the percent property. So my question is, how do you pull an extra parameter on the datastore building block of code when you have one extra parameter that is not usual on EXTjs, in my case the percent?
I tried doing a metachange on the JSONReader, but all I get is percent:"percent" on the properties as I inspect the datastore after it's creation.

Ext.data.JsonReader has a property jsonData which is exactly what you need. A quick example:
Ext.onReady(function() {
var store = new Ext.data.JsonStore({
url: 'data/test.json',
root: 'dataRoot',
fields: ['fieldA', 'fieldB'],
idProperty: 'id',
storeId: 'myStore'
});
store.on('load', function(store) {
console.log(store.reader.jsonData.someOtherProperty);
});
store.load();
});
and the data/test.json looks like this:
{
dataRoot: [{
id: 0,
fieldA: 'a',
fieldB: 'b'
}],
someOtherProperty: 'abc'
}
There could also be an alternative approach that you manually (not via store.load()) perform Ext.Ajax request, use the properties you need and then manually call Ext.data.JsonStore.loadData() using the data you got from Ajax request.

Related

Use the same data for multiple tables with tabulator

I'm using jQuery and tabulator to create a fairly simple webpage showing the progress of various live events. I have three table elements on the page showing events in different states. Broadly speaking I have a table for events that are 'Live', 'Finished' and 'Upcoming'.
The tabulator code for each table looks a bit like this:
var eventTable = {
layout:"fitColumns",
columns:[
{title:"Event ID", field:"eventID"},
{title:"Event name", field:"eventName"},
{title:"Event status", field:"eventStatus"}
]
};
I can then generate and populate the tables using data retrieved from the server using an AJAX call:
$('#live-events-table').tabulator(eventTable);
$('#live-events-table').tabulator("setData", "/cgi-bin/getevents.py");
$('#live-events-table').tabulator("setFilter", "status", "in", ["intermission", "mid-event"]);
Then similar code for the finished and upcoming tables.
This creates three requests for getevents.py every time the page is updated. This is undesirable because the data is pulled from another API and I want to avoid sending multiple identical requests. Also, there's a (small) chance the data could change between requests.
Is there a way of using the same data to populate all three tables?
Learnt something today. Never heard of Tabulator. I've been using DataTables for this sort of advanced tabular layout in the form of a jQuery plugin. Tabulator looks promising. Will have to explore more in the future.
In the docs I see Tabulator - Set Table Data, lots of alternative options available to set the data.
Hope I am understanding the problem correctly.
My thoughts/flow for tacking this problem would be:
Assuming your doing this already: Prep server side (getevents.py) needs to return all 'Live', 'Finished' and 'Upcoming' rows in JSON together in 1 response. How do I make a JSON object with multiple arrays?.
Client side on doc ready(), makes a jQuery ajax call to fetch this data before 3 x tabulators are built/called.
You can use a loading indicator. So the client sees something is happening in the 3 x before replaced by jQuery tabulator once the data is returned and you built with tabulator.
In the ajax success callback function you can iterate over the returned json object (containing the 3 x eventTypes). You might have to JSON.parse() if you store it in a JavaScript variable to iterate over.
Now get your specific array of event types nested objects arrays/json.
Then call your tabulator creation methods using the setData pointing to each specific JavaScript array containing the relevant data.
Not sure if this falls under "premature optimization", but I would proceed as the problem itself is rather fun to solve, but you know the requirements/needs better than I.
Good luck.
I fixed this fairly simply, using suggestions from #RoryGS.
Define the table options in a variable, as before:
var eventTable = {
layout:"fitColumns",
columns:[
{title:"Event ID", field:"eventID"},
{title:"Event name", field:"eventName"},
{title:"Event status", field:"eventStatus"}
]
};
Then make a jQuery ajax call to fetch the data, and build the table(s) in the success option of the function:
$(function() {
$.ajax({
dataType: "json",
url: "/cgi-bin/getevents.py",
success: function(data, status){
$('#live-events-table').tabulator(eventTable);
$('#finished-events-table').tabulator(eventTable);
$('#live-events-table').tabulator("setData", data);
$('#live-events-table').tabulator("setFilter", "status", "in", ["intermission", "mid-event"]);
$('#finished-events-table').tabulator("setData", data);
$('#finished-events-table').tabulator("setFilter", "status", "in", ["post-event"]);
}
})})
It seems to be necessary to set the data individually for each table. I would like to specify the data in the constructor, but this doesn't seem to work. I will continue to try to refine this.
If you are getting the data from a URL you can pass it into the ajaxURL property in the table constructor and tabulator will make the request for you:
$("#example-table").tabulator({
ajaxURL:"/cgi-bin/getevents.pyw", //ajax URL
columns:[...] //define columns etc
});

Update a OnDemandGrid based on dstore/Rest result in POST and not PUT

I am puzzled.
I have an OnDemandGrid editable, and under it i have a dstore/Rest collection pointing to my backend (in PHP).
The OnDemandGrid is mixed with the Editor... I can edit my data, but i cannot save it. What i receive on the server side is a "POST" request to insert a full row in the collection... And i never recieve the update.
Should'nt i receive a PUT request instead? I am using id's in the data...
This is the client-side part:
function (...)
{
var EditGrid = declare([ OnDemandGrid, Keyboard, Editor ]);
var coll = new Rest({
target: 'my.php/x/',
idProperty: 'id',
rangeStartParam: 'range',
rangeCountParam: 'limit',
sortParam: 'sort'
});
var grid = new EditGrid({ columns: {
user_name:{
label: 'User name',
editor: 'text',
editOn: 'click, dbclick',
autoSave: true,
}},
collection: coll }, 'grid' );
grid.startup();
}
I correctly receive the GET query to populate the table... Then, after editing a row and hitting "return", i get a POST!
The server side is a bit more complex to show here... Basically, on GET i do an SQL query and json-ize the results, while on POST i just return this:
http_response_code(201);
header("location: ".$_SERVER['PATH_INFO'].$id);
Where $id is the same ID i received from the request...
After the POST, i don't receive anything else. And in the POST data, i only ever receive a copy of the old, not modified, row... I never receive the "new" edited data.
It seems to me i should receive a PUT request at some point... I tried the browser debugger, server logs, nothing anywhere.
Can anybody help me out here?
I finally fixed it.
It's very convoluted and very little documented all this mess. I had to dig into the browser debugger and dgrid/Rest source code a bit.
So the problem was all in my REST backend. It turns out dgrid does a GET before the PUT/POST requesting the item to be modified, and it does a GET with only one record by asking for the specific "id". It make sense.
Well, my backend would return an ARRAY with one element in it, in JSON format. This was the error! This is not properly parsed by dgrid and it led to the POST instead of PUT.
Once i fixed the GET backend to return a single JSON item instead of an array with one JSON item inside, dgrid started sending the correct PUTs.

Backbone.js - make POST request without saving a model

I'm wondering is there a possibility to make this.model.save(data, options) in Backbone without writing data to model?
I have a server endpoint where I need to POST json { field1: 'bbb', field2: 'aaa' } - server writes these fields into db like list: [{ field1: 'bbb', field2: 'aaa' }].
The problem is that Backbone adds these fields to model as well. And I have model like { id: '111', field1: 'bbb', field2: 'aaa', list: [{ field1: 'bbb', field2: 'aaa' }] } and that's wrong..
Is there a way to make save without writing send data to model? Or maybe simply use jquery $.post method and set model on success?
I think the easiest way to fix this would be to either change the data returned by the server, or override the parse method in your model and remove the extra attribute.
A second thought would be to give your moel a single attribute of list and set that with the data dict and have the server return the same. This won't be 100% compatible with general Backbone model usage though.
gotta go..
You can define sync function and make ajax there
You can define parse function and write something like this
parse:function(data)
{
return data.list;
}
2 is the better approach. If setting some field will affect another one, server will return it and you will always have actual data in the model.

ExtJS 4.1 - Retrieve hasOne information for Nested JSON

I am attempting to retrieve the information for a Model and an associated model that contains a hasOne association. I was referencing the following Sencha documentation page (http://docs.sencha.com/ext-js/4-1/#!/guide/data). I currently have the following sample code working:
var Mtd = Ext.ModelMgr.getModel('Mtd');
Mtd.load(4, {
success: function(mtd){
console.log("Loaded! " + mtd.get('id'));
mtd.getTreatmentdesign(function(treatment,operation){
console.log(treatment.get('id'));
}, this);
}
});
Now, when I call mtd.getTreatmentdesign(), I notice that two requests are made to retrieve information. The first one is to retrieve the Mtd information which I am expecting but then it's also making a request to retrieve the Treatmentdesign information. The response for the Mtd contains the Mtd information as well as the Treatmentdesign information. So I want to process the Mtd and Treatmentdesign information with one request. It puzzled me that the documentation stated the following:
You may be wondering why we passed a success function to the User.load call but didn't have to do so when accessing the User's posts and comments. This is because the above example assumes that when we make a request to get a user the server returns the user data in addition to all of its nested Posts and Comments. By setting up associations as we did above, the framework can automatically parse out nested data in a single request.
So how can I retrieve associated information without having to make another request? I simply just want to use all the json from a single request as opposed to having to make multiple requests.
Be sure to set the associationKey config on the HasOne association to the property that contains the data for the associated model. By default, this is the name of the associated model class in all lowercase letters.
For instance, if the data for an Mtd record is returned by the server in the form
{
...
treatmentDesign: {
...
}
}
set the associationKey to 'treatmentDesign'.
Here's an example in action: http://jsfiddle.net/HP6fq/3/
Yes, associationKey works
Ext.define('User', {
extend:'Ext.data.Model',
fields: ['id', 'name', 'status'],
associations: [{ type: 'hasOne', model: 'Status', associationKey: 'status' }]
});
Ext.define('Status', {
extend:'Ext.data.Model',
fields: ['id', 'title'],
});
Demo here

Getting started with extJS

I don't get what I'm doing wrong.
I'm trying to populate a form from a JSON string from the server and it doesn't work. I get nothing at all back. I examine the object and it's undefined. I've been beating my head against the wall for 3 days now. I need a simple example that works and I'll build from there.
Here's the simple example that I've been trying to use:
var messages = new Ext.data.JsonStore({
url: '/user/' + user_id,
method: 'GET',
root: 'user',
fields: [
{name: 'user_id'},
{name: 'first_name'}
],
listeners: {
load: messagesLoaded
}
});
messages.load();
function messagesLoaded(messages) {
console.log(messages);
}
Here's my JSON string:
{"success":"true","user":{"user_id":"2","first_name":"Test","last_name":"Test","email":null,"password":null,"city_id":"6379","birth_date":"2009-06-09","gender":"F","created_on":"2009-06-01 17:21:07","updated_on":"2009-06-14 17:20:14","active":"Y","cuisine_id":null}}
I really don't see what I'm doing wrong, but my JSON string isn't loading. Thanks!
Ok so you're almost there, but one problem. The root ("user" in this case) has to be an array. Even if it's an array with only 1 object. Ext.data.JsonReader (the default reader for a Ext.data.JsonStore) only accepts an array of results.
So your javascript looks just fine, but the JSON object returned by the server needs to look more like this.
{
"success":"true",
"user": [{
"user_id":"2",
"first_name":"Test",
"last_name":"Test",
"email":null,
"password":null,
"city_id":"6379",
"birth_date":"2009-06-09",
"gender":"F",
"created_on":"2009-06-01 17:21:07",
"updated_on":"2009-06-14 17:20:14",
"active":"Y",
"cuisine_id":null
}]
}
One more thing, consoloe.logging your store object will produce something like [Object] in Firebug... not too useful. You should either console.dir it, or log your actual data instead.
One comment about loading your form, once you get past loading your JSON (even though this example does not show that). Make sure your form is actually rendered before trying to load it with data, e.g. if trying to use something like form.loadRecord. Otherwise you'll end up with an empty form and no errors.

Categories

Resources