Extjs setRootNode() on TreeGrid isn't loading children of the object - javascript

I am currently building a project using Ext JS 4.2 this is the first time I am using TreeGrids and TreeStores so it is very possible I am misunderstanding the structure somewhere. Currently the issue seems to be when I use setRootNode(JSON) it refreshes the tree but it only displays the root node and none of its children. Here is what it currently creates.
Using the developer tools in chrome this is what the object looks like before it is passed in.
Object {text: ".", Item Number: "P00001", original: "P00001", children: Array[2]}
Once it is passed in using setRootNode(Object) it only displays the root. However I have noticed that looking at the grid.tree.root property all the data is in there which makes me wonder why it is not being loaded into the treegrid.
Here is a snippet of my code that loads the necessary data. var grid refers to the tree panel component. store.load causes a jsp call that loads in meta data that dynamically creates the columns / fields for the treegrid and model which is functioning correctly.
onPanelAfterRender: function(){
var grid = Ext.getCmp('BOMGrid');
var store = Ext.getStore('BOMGridStore');
store.load();
//var me = Ext.getCmp('main-page');
grid.setLoading('Loading BOM...');
Ext.Ajax.request({
url : 'loadbom.jsp',
timeout: 300000,
params : {
},
success: function (response, opt) {
grid.setLoading(false);
var res = Ext.JSON.decode(response.responseText);
if (res.success) {
console.debug(res.results[0]);
grid.setRootNode(res.results[0]);
}
else {
console.debug("JSON failure");
Ext.Msg.alert('Error', 'Invalid part number');
}
},
failure: function(response,options){
console.debug("major failure");
grid.setLoading(false);
Ext.Msg.alert('Error', 'Connection failed<br>' + response.responseText);
}
});
}
If you need additional information or for me to clarify something please ask me I would appreciate any help that I could possibly get.

Related

How to copy data from OData v4 to JSON with SAP UI5?

I'm using OData v4 to load data from my backend to my frontend (developed with SAP UI5) and I am using a form to display a detail page. When I click the "edit" button I'm able to edit the data. My implementation is similar to this example: https://sapui5.hana.ondemand.com/explored.html#/sample/sap.ui.layout.sample.Form354/code/Page.controller.js
When editing something, the data is directly edited at the model and, therefore, updated at the backend. However, I want to be able to choose if I want to save the changes or if I want to cancel the edit before it is updated at the backend.
I read on other questions that one can copy the ODataModel to a JSONModel and use that copy instead, by doing something like:
var oModel = this.getView().getModel();
var oModelJson = new sap.ui.model.json.JSONModel();
oModel.read("/Data", {
success: function(oData, response) {
oModelJson.setData(oData);
sap.ui.getCore().setModel(oModelJson, "oJSONModel");
alert("Success!");
},
error: function(response) {
alert("Error");
}
});
However, the read method seems not to be available for OData v4. the code of my controller where the data is loaded looks like following:
onInit: function() {
this.oModel = new ODataModel({
groupId : "$direct",
synchronizationMode : "None",
serviceUrl : '/odata/'
});
this.getView().setModel(this.oModel, 'oModel');
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.getRoute("details").attachPatternMatched(this._onObjectMatched, this);
this._showFormFragment("display");
},
_onObjectMatched: function (oEvent) {
this.getView().bindElement({
path: "/Data(" + oEvent.getParameter("arguments").dataPath + ")",
model: "oModel"
});
//I want to copy the data from the ODataModel to the JSONModel here
},
What's the best way to accomplish this? And how to do it with OData v4?
I suppose you want to resetChanges in case user cancels the save.
For V2 ODataModel, there is deferedGroup concept which you can use to resetChanges or submitChanges.
I have not much experience with V4. Though from the documentation, it is possible.
Please try to pass a updateGroupId in the constructor. Then you can choose resetChanges or submitBatch by group Id.
mParameters.updateGroupId? The group ID that is used for update requests. If no update group ID is specified, mParameters.groupId is used. Valid update group IDs are undefined, '$auto', '$direct' or an application group ID, which is a non-empty string consisting of alphanumeric characters from the basic Latin alphabet, including the underscore.
Thank you!

Enabling Backbone.emulateJSON() - POST issues

I am writing an app that uses a codeigniter backend custom REST service with a backbone front end. I am having trouble with creating a post(i.e. comment) in my db. I have read that enabling Backbone.emulateJSON() may be able to fix this. In summary I'm looking for where to include this line. A longer explanantion...
When I submit my form manually to create a new post the data is saved fine as expected. When I attempt the following in my postAddView...
save: function(e) {
e.preventDefault();
var that = this;
var postCollection = this.postCollection;
var newPost = {
message:"this is a post",
author_id:"22",
location:"New York"
}
postCollection.create(
newPost,
{
wait: true,
success: function(response){
console.log("successful" + response.toJSON);
},
error:function(err) {
console.log("this is the error "+ err.toJSON);
}
});
return this;
}
As as a result a new record is saved in my DB but no data is populated. Inspecting and comparing the networks in chrome shows that the ajax call from the backbone app submits it as 'request payload' vs. the form submission which is 'form data' (both are POSTS).
Based on my code above if anyone has any advice it would be much appreciated - however I'm also looking where to include backbone.emulateJSON() as many other posts have referenced this as a fix.
emulateJSON is not a function
Backbone.emulateJSON = true
http://backbonejs.org/#Sync-emulateJSON

Ext: how can I use data from an ajax request to modify an existing Javascript element?

For days now I've been searching for an explanation on how to do this right. I tried to find a decent tutorial for either JS or Ajax, but all the one's I found were rather basic and didn't go deep enough. When I want to solve a problem with Python, I go to Python.org, for PHP I use php.net, but I haven't found a decent ressource for JS and Ajax yet. Any tips are appreciated.
So I'll try to explain what I did. I have a rather simple page, it has a div on the left and a div on the right. Within the left one, a tree is rendered, representing a registry, within the right one, values are displayed and edited.
The tree is stored in a global variable. I have read all the warnings about using global variables, but I think it's justified in this case. Whenever this page is accessed, the tree is displayed.
var tree;
...
function initTree(treeRootConfig) {
return new Ext.tree.TreePanel({
renderTo : 'tree'
,width : 500
,height : 498
,autoScroll : true
,resizable : true
,useArrows : false
,animate : true
,loader : {
dataUrl : urls.urlLoadTree,
listeners: { beforeload : function(treeLoader, node) {} }
},listeners: {
click : function(node, e) { valueGrid.load(node.id); }
,contextmenu : function(node, e) {
cmPath.node = node;
cmPath.showAt(e.getXY());
},
},root : treeRootConfig
});
}
There is a textfield which holds a textual represantation of the path, that the tree is displaying.
function initTextfieldPath() {
return new Ext.form.TextField({
fieldClass : 'textfieldPath',
applyTo : 'path',
enableKeyEvents: 'true',
listeners : { change : function() { refreshTree(); } },
});
}
Every node is a "folder" in the path. Now when a new node is accessed, the value of the textfield is modified accordingly. This is working fine. When a new path is entered into the textfield, I want the tree to be reloaded to show the nodes. The path is parsed and and then I use Ajax to get the nodes out of the database. This works to the point, that I get the string represantation of the node, encode via JSON and try to set the node as new root for the tree.
function refreshTree() {
Ext.Ajax.request({
url : urls.DirectAccess
,scope : tree
,params : { path: textfieldPath.getValue() }
,success: function(response, opts) {
alert(response.responseText);
tree.setRootNode(Ext.util.JSON.decode(response.responseText)); }
,failure: function(response, opts) { noConnection(response); }
});
}
As you can imagine, the alert is only in there for testing purposes. When the server request is done, it displays the string represantation of the node that was fetched from the database. Just setting this node to the tree is something I cannot get done.
The ext license that we have is for Ext 3.4.0.
The problem was something else entirely. I thought it was not possible to communicate with a variable declared outside of an Ajax statement from within the Ajax statement. Turns out I had a '[' and a ']' too much. My target was expecting something like this '' but I gave it an array with only one member '[]'. It is kinda weird though, because in other cases Ext will only accept nodes as an array, no matter how many there are.

Make Twitter Bootstrap's typead search within multiple fields

By default, the typeahead plugin makes use of a single data source in order to fetch the results. What I would like is for it to search within multiple fields, so if say, I have:
var items = [
{'title': 'Acceptable', 'description': 'Good, but not great'}
]
It will search on both the title and description fields, ideally via AJAX.
Is this possible with this plugin?
Typeahead does not support using JSON objects without two tweaks. There are few pull-requests in Github for this, and I have submitted one myself, but, currently, you must manually override select and render. Additionally, you must also override highlighter, matcher, sorter, and updater, but those can done via the options passed into the typeahead.
var typeahead = control.typeahead({ /* ... */ }).data('typeahead');
// manually override select and render
// (change attr('data-value' ...) to data('value' ...))
// otherwise both functions are exact copies
typeahead.select = function() {
var val = this.$menu.find('.active').data('value')
this.$element.val(this.updater(val)).change()
return this.hide()
};
typeahead.render = function(items) {
var that = this
items = $(items).map(function (i, item) {
i = $(that.options.item).data('value', item)
i.find('a').html(that.highlighter(item))
return i[0]
});
items.first().addClass('active')
this.$menu.html(items)
return this
};
If you need help with the other ones, then let me know, but the gist of it is:
control.typehead({
matcher: function (item) {
var lcQuery = this.query.toLowerCase();
return ~item.title.toLowerCase().indexOf(lcQuery)
|| ~item.description.toLowerCase().indexOf(lcQuery);
}
};
I also have a JFiddle example related to the pull request that I made, but the sorting functions do not exist in 2.3.1, or even 3.x without the pull request being accepted, so you will have to override sorter in its entirety to effectively repeat what I did with matcher above (checking both while sorting).
As for the AJAX call, you can override the source method in the passed in options to get AJAX functionality. By not returning to the source call, it assumes that the second parameter, process, will be invoked with results.
control.typehead({
minLength: 3,
source: function(query, process) {
$.ajax({
url: url + encodeURIComponent(query),
type: 'GET',
success: process,
error: function() { /* ... */ }
});
}
});
Typeahead added support for multiple field searching in v10.3
https://github.com/twitter/typeahead.js/pull/811
Usage:
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title', 'description'),

How can I preserve the search filters in jqGrid on page reload?

I found many discussions that were close to what I need, and this question is the
closest - How can I set postData._search to true in the request in jqGrid?.
As I'm struggling with almost the same problem, and just can't get it working - I want to setup "search" and "filters" during the initial loading of the jqGrid - say, on the page reload, and I have my filters stored in the session - and I tried everything I found in Oleg's examples - it just doesn't work!
That's what I'm trying to do -
loadBeforeSend: function (xhr) {
var grid = jQuery('#' + block_id);
var postData = grid.jqGrid('getGridParam','postData');
jQuery.extend(postData,{filters:MyFilters});
grid.jqGrid('setGridParam', {search: true, postData: postData});
console.log(grid.jqGrid('getGridParam','postData'));
}
The console printout shows that the filters are in place, but the _search is still false, and the actual Post gets sent even with no filters:
_search false
block_id report_block_1table
nd 1297451574526
page 1
rows 25
sidx id
sord desc
However, if I put exactly the same code - with the addition of
grid.trigger("reloadGrid");
line - into some button's onClickButton function, and later click the button - everything works; but I need to make it work on "page reload"!
Any ideas? It's driving me crazy...
It seems to me that you are not the first person who ask the same question. Recently I asked on the close question (read many comments to the answer). Another old answer including the demo could probably answer on some your opened questions.
Your code using beforeRequest don't work just because the function beforeRequest will be caled immediately before the ajax call and the changing of the search parameter is too late. Moreover overwiting of filters everytime is probably not the best idea. In the case the user will not able to set any other grid filter.
So I can repeat, that the imlementation of the solution which you need is very simple. You should just set filters property of the postData parameter of jqGrid to the filter which you need and set another jqGrid parameter search:true additionally. It's all! Later the user will be able to open advance searching dialog and overwrite the filters. The user can also click on "Reset" button of the advance searching dialog and set filters to empty string and search:false.
For better understanding I have to clear how search parameter or some other jqGrid will be used in the URL. There are parameter prmNames of jqGrid which defines the names of parameters send as a part of URL or as a part of data POSTed to the server. The default value of prmNames contain search:"_search" and the code of internal populate function used by jqGrid has the following simplified code fragment:
var prm = {}, pN=ts.p.prmNames;
if(pN.search !== null) {prm[pN.search] = ts.p.search;}
if(pN.nd !== null) {prm[pN.nd] = new Date().getTime();}
if(pN.rows !== null) {prm[pN.rows]= ts.p.rowNum;}
if(pN.page !== null) {prm[pN.page]= ts.p.page;}
if(pN.sort !== null) {prm[pN.sort]= ts.p.sortname;}
if(pN.order !== null) {prm[pN.order]= ts.p.sortorder;}
...
$.extend(ts.p.postData,prm);
where
prmNames: {page:"page",rows:"rows", sort: "sidx",order: "sord", search:"_search",
nd:"nd", id:"id",oper:"oper",editoper:"edit",addoper:"add",
deloper:"del", subgridid:"id", npage: null, totalrows:"totalrows"}
So to set _search parameter of URL one should set search parameter of jqGrid.
Look at the following demo. You can easy to verify using Fiddler of Firebug that the jqGrid from the page send HTTP GET with the following url:
http://www.ok-soft-gmbh.com/jqGrid/MultisearchFilterAtStart1.json?filters=%7B%22groupOp%22%3A%22AND%22%2C%22rules%22%3A%5B%7B%22field%22%3A%22invdate%22%2C%22op%22%3A%22gt%22%2C%22data%22%3A%222007-09-06%22%7D%2C%7B%22field%22%3A%22invdate%22%2C%22op%22%3A%22lt%22%2C%22data%22%3A%222007-10-04%22%7D%2C%7B%22field%22%3A%22name%22%2C%22op%22%3A%22bw%22%2C%22data%22%3A%22test%22%7D%5D%7D&_search=true&nd=1297508504770&rows=10&page=1&sidx=id&sord=asc
So it do exactly what you need. The code of the demo contain the following code fragment:
$("#list").jqGrid({
url: 'MultisearchFilterAtStart1.json',
datatype: "json",
postData: {
filters:'{"groupOp":"AND","rules":['+
'{"field":"invdate","op":"gt","data":"2007-09-06"}'+
',{"field":"invdate","op":"lt","data":"2007-10-04"}'+
',{"field":"name","op":"bw","data":"test"}]}'
},
search:true,
// ...
});
#Oleg Oleg's answer works like a charm but just for the first time.
For me when I reload the grid, filters and search flag are not set up.
With the following code each time I reload the grid it also sends the filters and search flag.
I use server side sort and pagination.
I'm using:
jQuery("#myGrid").navGrid("#myPager", {search: true, refresh: true, edit: false,
add:false, del:false}, {}, {}, {}, {});
On the grid definition:
beforeRequest: function() {
// filter to be added on each request
var filterObj1 = {"field":"myField","op":"eq","data":"myValue"};
var grid = jQuery("#myGrid");
var postdata = grid.jqGrid('getGridParam', 'postData');
if(postdata != undefined && postdata.filters != undefined ) {
postdata.filters = jQuery.jgrid.parse(postdata.filters);
//Remove if current field exists
postdata.filters.rules = jQuery.grep(postdata.filters.rules, function(value) {
if(value.field != 'myField')
return value;
});
// Add new filters
postdata.filters.rules.push(filterObj1);
} else {
jQuery.extend(postdata, {
filters: {
"groupOp":"AND",
"rules":[filterObj1]
}
});
// more filters in the way: postdata.filters.rules.push(filterObj1);
}
postdata.filters = JSON.stringify(postdata.filters);
postdata._search = true;
return [true,''];
}

Categories

Resources