In Dojo how to add node to a tree in a sorted way? - dojo

In my Dojo application, I had a tree with nodes sorted by their name. Like this :
I already built a New form addition, and it can add a new node to this tree, but always at the bottom. Is there a way to insert this newly added node to the store in a correct sorted position? So if I am about to add 000-011 - Biaya Teknis Pengacara to this tree, it should be ended up this way :
To achieve this, currently I must refresh my browser. Surely, this is not what all user wanted.. :)
For the code addition of node itself, here it is:
//TOFIX : add in a sorted way
akunStore.newItem(
{"id":data.id.toString(),"name":data.name},
{"parent": groupsModel.root, "attribute":"groups"}
);
akunStore.save();
akunStore.fetch();
I add the fetch() as shown above, but it didn't work, currently.

Use the sort attribute in your call to the fetch() method of your data store. Try something like :
akunStore.fetch({
sort: [
{ attribute: "youFirstSortField" },
{ attribute: "aSecondSortField" }
]
});
You can also specify a descending order by adding "descending : true" in your sort params... more on that here : http://dojotoolkit.org/reference-guide/quickstart/data/usingdatastores/sorting.html#quickstart-data-usingdatastores-sorting

Related

Conditional rendering on load with AMP-HTML

I have a JSON file and I'd like to render elements based on the value of a property in JSON file. Let's think the JSON is something like this:
{"Items":
[
{"Title":"Text","Type" : 1,...},
{"Title":"Text","Type" : 0,...},
{"Title":"Text","Type" : 0,...},
{"Title":"Text","Type" : 1,...},
{"Title":"Text","Type" : 0,...}
]
}
in my AMP project, I used something like this:
<div [class]="{{type}} == 0 ? 'class-0' : 'class-0' ">DATA</div>
but this will only work when the state changes, not in rendering for first time. Is there any way around this?
As far as I know it is impossible to evaluate bind expressions on page load. The docs clearly say as follows :
For performance and to avoid the risk of unexpected content jumping, amp-bind does not evaluate expressions on page load. This means that the visual elements should be given a default state and not rely amp-bind for initial render.
However amp-access can perform conditional rendering on page load without user interaction. Depending on your requirement you should be able to achieve this using amp-access.

Adding an item to a dojo store using 'before' option

I've got a dijit/Tree connected to a dijit/Tree/ObjectStoreModel which is in turn connected to a dojo/store/Memory wrapped in dojo/store/Observable - essentially as per the example on the dijit/tree documentation.
It's working mostly fine: I preload the store with some objects and can add other objects in using store.add(item). The data is hierarchical and that also is working by setting the parent property on each item added to the store.
However, I want to be able to specify how within a parent sub items should be ordered. e.g. if I've got an item with id "parent_1" and I add two items (say, "item_A", "item_B") both with parent set to "parent_1" then I'll end up with:
parent_1
item_A
item_B
However, I want item_B to be placed above item_A.
store.add supports a second parameter: an object of properties, one of which is 'before'. My understanding is that when you set 'before' to another object in the store, it should be placed before it. so, when I add item_B I use:
var item_A = store.get("item_A");
var item_B = { id: "item_B", parent: "parent_1", ... };
store.add(item_B, { before: item_A });
However, it's not working. item_B is always simply appended at the end. Does anyone know how to make this work? Thanks!
Looking at the source, it doesn't look as if dojo/store/Memory supports the before PutDirective.
If you want this feature, I suspect you will have to submit a Dojo feature request, or patch/augment dojo/store/Memory to provide the function you require.

Extjs4 Combo's and Stores: Remove filter when queryMode=local?

I'm getting frustrated because my store keeps getting filtered whenever I use it to back a combofield. Is there any way I can disable this?
The Scenario
I have a Store with a data field on it; an array of objects loaded when the store is instantiated. I use this store to drive a bunch of combo's in different areas of my app. Unfortunately, my combos are applying filters on the store, causing other combos using the same store to only display the filtered values later on, not the whole list.
Workarounds
My goofy workaround is to call combo.getStore().clearFilter() after I'm done with the combo, but that's going to get old very quick, and probably introduce a bug somewhere, I'm sure.
If I remove queryMode:'local' from my combo's config, all is well, except that now the handy type-ahead feature no longer works; I'm just shown a list of items in a drop-down that I can't even navigate around my typing letters of matching items. That's worse than a regular html select tag!
Any ideas?
Thanks!
You can't do that since the filtering is applied not on the combo but on the store. You could try creating multiple instances of the same store and work with that. Though I don't know if it'll work.
Ext.create('combo', {
//other config
store : Ext.create('my.store')
});
It'll work if you make the combo non-editable since no filtering can be applied then. But, as you say, you need the type ahead feature, you'll need to create multiple instances of the store.
In light of the fact that combos will add filters on the backing store, hence affecting all combos that use the store within my application, I've opted to add an override to the combo class so it will clear the filter on the store when the combo box is destroyed.
Ext.define('MAP.override.Combo', {
override : 'Ext.form.field.ComboBox',
initComponent : function()
{
this.callParent(arguments);
this.on('beforedestroy',function(combo){
if(combo.leaveFilter === true) return;
console.log('clearing filter on store');
combo.getStore().clearFilter();
});
}
});
it's a bit of a hack, but I do allow for the escape hatch of indicating not to clear the filters, too.
The simplest way I have found to handle this solution is to add the following listener to the combo:
listeners: {
beforequery: function(queryPlan){
queryPlan.query = true;
}
}
by default queryPlan.query is the text currently in the combo field which is used for filtering. Setting it to false cancels the query, but setting it to true allows the query to go through without a filter value, therefore keeping all values in the drop down list for all combo fields.
I've had similar problem with ExtJS 4.2 and combo. Store kept being filtered but I couldn't use clearFilter() because after that combo was unusable. My solution, which worked, is this listener on combo:
listeners: {
blur: function(combo) {
if (combo.queryFilter) {
combo.queryFilter.setValue('');
combo.getStore().filter();
}
}
}

ExtJS 4: Add children tree nodes to a non-Root node dynamically?

I am trying to add children tree nodes to a non-Root node dynamically when it's selected.
This is how I implemented it:
First, I populate my tree with a TreeStore then to dynamically add children tree nodes, I handle it on the itemexpand event in tree Controller.
//pThis is a NodeInterface obj of the selected node
itemexpand: function (pThis, pEOpts) {
//type is an attribute that I added so that I know what type of node that got selected
if (pThis.raw.type === 'Staff' && !pThis.hasChildNodes()) {
var staffNodeAry = [{text:"Teachers", type:"ChildStaff", leaf: false},
{text:"Principals", type:"ChildStaff", leaf: false}];
pThis.appendChild(staffNodeAry);
}
}
This worked quite good because I am able to see both "Teachers" and "Principals" node under "Staff" type but there are 2 issues that I found so far:
1) There's this error on the console:
Uncaught TypeError: Cannot read property 'internalId' of undefined
I don't know why but if anyone could enlighten that would be great.
2) When I expand either "Teachers" and "Principals", the NodeInterface obj that's returned by itemexpand has an undefined raw object.
So I couldn't do this: pThis.raw.type
From my understanding, I don't need to create a new TreeStore to add any new children nodes, I thought that by creating an array of objects that adhere to NodeInterface should be enough but I might be wrong.
If anyone could point me to the right direction, that would be great.
Handi
More info:
What I did was actually following the ExtJs 4 documentation so I believe this is a bug on ExtJs 4 framework.
I also tested this with Extjs-4.1.0-rc3 and it also produced the same error.
I have resolved this issue changing the event itemexpand with the event afteritemexpand. I have no documentation to justify this. The debugger says to me that the view listen for the itemexpand event and do something that goes wrong if add a node manually...
For the question number 2: you have no raw object because it is created by the reader of the store after the load operation. So if you add a node by hand the raw object does not exists.
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Model-property-raw
The documentation for .appendChild() functions says:
node : Ext.data.NodeInterface/Ext.data.NodeInterface[]
The node or Array of nodes to append
And you are trying to append an array of 2 objects, but they are not "NodeInterface" instances. So you should create them properly like so:
var nodeToAppend1 = pThis.createNode({text:"Teachers", type:"ChildStaff", leaf: false});
pThis.appendChild(nodeToAppend1);
I remember making the same mistake a year ago, so I hope this helps.
I think it happens because your Ext.TreePanel working asyncroniously. So add process is:
Append Child, add virtual child leaf to your tree, with red mark in corner
Call store's create api
Receive response, if it success=true, change with virtual
The goal of changing is set internakId property, so you can add new child only after this change happens. I think better is write some recursive function and bind it to store's added event
tree.getStore().on('update', addChild);
or
tree.getStore().load({
success: function() {
addChild()
});

Sencha Touch 2: Insert into TreeStore/NestedList

I'm using a NestedList with a underlying TreeStore. Now I want to add items to the NestedList as leafs.
How can I do this?
Currently my code (Controller, onAddButtonTapped) looks like this:
var store = Ext.getStore('menuStore');
var customerAreaNode = store.getRoot().getChildAt(1);
customerAreaNode.appendChild({name: "text", leaf:true});
customerAreaNode.expand();
store.sync();
This code results in two new empty listentries on leaf level (behind the correct node) and one new listentry on node level.
Every new entry has no names shown in the NestedList but every item contains "text" in their name field. Curiously one of the new entries at leaf level is not typed to the underlying Model. So the model-corresponding methods could't be found:
Uncaught TypeError: Cannot call method 'getSelectedName' of undefined
Does anybody know a easy tutorial how to add data into NestedList/TreeStore? I could not find one good example in the sencha touch docs.
The default display field for leaf items is "text". You can get the information from here. If you want to use "text" as display field, then you need to change this line to
customerAreaNode.appendChild({text: "text", leaf:true});
Or you can change your nested list's display field, so your model do not need to change for this time.
yournestedlist.setDisplayField('name');
Hope this helps.
In my case i used to update root and child nodes like the following way
Ext.getStore('Contactsstore').getAt(1).getChildAt(0).set('Email',contactemail);
Ext.getStore('Contactsstore').getAt(1).set('ContactTitle',contacttitle);