On my page I have 2 trees.
There is form on the page. One tree is shown on the page and another inside the form.
I have create trees as below:
var myTree1 = Ext.create('Ext.tree.Panel', {
store: store, //where store is hardcoded json tree data
....
});
similarly myTree2 is declared with different store. It is shown inside a form.
When I select on any node on myTree2 and click on create button then I must be able to add a new leaf node inside myTree1 at the same index.
Help I need are:
1. How to get index of selected node.
2. How to go to the index in myTree1, should be equal to the selected index myTree2.
3. How to add a leaf node at specific index.
For reference:
Ext JS 4 TreePanel documentation
Ext JS 4 NodeInterface documentation
The select event provides both the index and the record. If you need general access to it, myTree1.getSelectionModel().getSelection() will return an array of records, which you can then check against the store to get the index.
I'm assuming you want to compare the selected records on both trees. Given the sample in #1, try this:
var tree1rec = myTree1.getSelectionModel().getSelection[0],
tree2rec = myTree2.getSelectionModel().getSelection[0];
// Perform comparison logic here
// Note that if you're using two different stores, you can't
// just do an equality test. You'll probably have to compare
// individual store values.
Nodes are inserted relative to existing nodes on the tree. So if you have a button click event:
function onButtonClick(button, eOpts) {
var rec = myTree1.getSelectionModel().getSelection[0];
if (rec) {
var childNode = rec.createNode(/* some object here */);
rec.appendChild(childNode);
}
}
The details will vary depending on your actual data, but this is the general pattern.
Related
I'm working on a project that requires me to update a UI based on how many values exist in the database. For instance, when 2 child values are created, the UI updates to contain two boxes.
Currently, my code determines how many child objects exist;
database.ref("parent").on('value', displayValue);
function displayValue(c){
total = c.numChildren()
}
From here, I create how ever many elements, based on this number. My problem however, is how to get the initial child name, in this case, "child1" to update elements such as the title text.
Is there a way to pull these values based off an index, like in a javascript array array[index]?
The Firebase Realtime Database API does not have a way to access child nodes by their index. The only way to pull a child by index, is by loading all children into an array in your code, and then access them by index there.
If you want to iterate over all the child nodes in your snapshot, you can do:
database.ref("parent").on('value', (snapshot) => {
snapshot.forEach((child) => {
console.log(child.key); // "child1", "child2"
console.log(child.child("data").val()); // "123", "123"
});
}
If you want to update a specific child, you specify the keys for the entire path. For example:
database.ref("parent").child("child1").child("data").set("456")
Or a bit shorter:
database.ref("parent/child1/data").set("456")
I am working on my first Ext JS project and have my source data downloaded from a web server held in a store. Now I want to have various grids all show some variation of that source data. For example, grid 1 would be the source data grouped by 1 particular column. Grid 2 would be grouped by a particular column, and where column X = 'variable'. So on and so on.
I am coming from a c# background working in WPF. So normally I would use observable collections, and run LINQ on the observable collection to form a new observable collection, then bind that new collection to my grid.
My question is, how can I run LINQ type queries on stores in EXT JS?
You can run LINQ type queries on stores in ExtJS: You can easily get a Collection from a store using the query or queryBy method.
But you can't work like this for your grids, because grids can't run solely on collections, they need a store each. You wouldn't want to use LINQ type queries for these stores.
If you are using ExtJS6, you can look into ChainedStore. You can bind each grid to a ChainedStore which has your data store as the source. Each ChainedStore can be filtered, sorted and grouped independently from the source and from other stores, by using the sort(), group() and addFilter() functions on the respective store.
If you are using an earlier version, you have to use multiple stores and copy all data from the main store manually. Please be aware that store.add() takes an array of records, not a collection. Instead of store.add(collection), use store.add(collection.getRange()). The getRange() function will return an array that contains all items in the collection.
To answer your question from the comment:
what if I need to do something as simple as create a new store, from store1, group everything by column1, and sum column2?
In ExtJS6, if you want to show the grouping and the sum in a grid, that would be something along:
var store2 = Ext.create('Ext.data.ChainedStore',{
source:store1, // use the data from the other store.
grouper:{
property:'someTestField' // grouping is done inside this store.
}
});
Ext.create('Ext.grid.Panel',{
store:store2,
features:[{
ftype:'groupingsummary' // a summary row for each group is provided by this
}],
columns:[{
xtype:'numbercolumn'
dataIndex: 'someTestField'
summaryType: 'sum' // this column should have the sum in the summary row.
}]
})
Untested and without warranty. If you want to do it without the grid, just calculate the sum, that would have to be done manually like this:
var sums = {};
store1.getGroups().each(function(group,i) {
sums[i] = 0;
group.each(function(record) {
sums[i] += record.get(propertyName);
});
});
Is it possible to change the context of an Ember view, specifically as regards the valueBinding? I have a matrix of text inputs with rows representing categories and columns representing days of the week. I don't want to save empty values or 0 values, but each input has some other data specific to it that needs to be saved if the user enters hours in that input. So, when generating the form, I create an array of objects, each of which is simply a javascript hash (if no existing entry exists for that field) or an ember-data record (if an entry already exists) and use each of these objects as the context for the view.
So, the idea is that if the user enters a zero or an empty string in a field with an existing value, that record is deleted and the context of the view is replaced with a simple hash that still contains the other relevant pieces of info for that field, in case the user comes back and sets that value again. Conversely, adding input to a field that was previously empty would create a new ember-data record using the values from the attached hash and the value of the input.
I've gotten as far as deleting existing records, which works, but the valueBinding for the text input remains bound to the record that's slated for deletion. I would like to change the context of the field to the placeholder hash immediately. If I commit the transaction and come back to that screen, the record has been deleted and the context is now a newly generated placeholder, but I would like to change the context of the TextField view (which I've extended) as soon as the value changes to zero/null. I've attempted using this.set('context') and this.set('valueBinding'), but neither work. Here's the code for my view so far. Can anyone help me out, or suggest a better alternative?
App.HourInputView = Ember.TextField.extend({
type: 'number',
init: function(){
this._super() ;
var context = this.get('context') ;
var ph = moment(this.get('context.cal_date')).format("dd") ;
this.set('placeholder',ph) ;
},
change: function(){
var val = this.get('value') ;
if (this.contextIsRecord() && (val===0 || val==='0' || val==='')) {
var record = this.get('context') ;
var new_ctx = this.get('context').getProperties('user','site','supervisor','category','cal_date') ;
new_ctx.total = null;
this.set('context',new_ctx) ;
this.set('valueBinding',"new_ctx.total") ;
record.deleteRecord() ;
}
},
//--
contextIsRecord: function() {
var ctx = this.get('context') ;
return (typeof ctx.deleteRecord === 'function') ;
}
}) ;
Holy cow, was I going about this one wrong. Walked away, had some lunch and came back and came up with a better solution. Instead of using a combo of actual Record objects and dummy hashes, I create a record object for each input and observe changes on each input. Any changes get added to a custom transaction. When the user clicks the save button, I commit the custom transaction and roll back the default transaction to get rid of all the irrelevant Record objects.
I have two ExtJs TreePanel. One tree is fully loaded (call it FLTree) and second one is partially loaded (call it PL tree). When user clicks on a node in fully loaded tree & that node is present in partially loaded tree, I want to fire the checkchange event for that node in partially loaded tree.
Is this possible?
Yes, Ext.tree.Panel has the itemclick event which is fired when an item is clicked (you need to add it in the controller or in the treepanel's listeners property.
The attributes are: someFunctionName: function(treeview, record, item, index, e, eOpts) { ... }
From the record variable you can get the data needed from the first tree's selected node.
To find the other treepanel you can use the up() and down() methods on the treeview:
var parentContainer = treeview.up('container_xtype[someProperty1=someValue1]');
you can walk up in the component hierarchy (get that parent container which contains both treepanels).
var pLtree = parentContainer.down('treepanel[someProperty2=someValue2]');
If the two treepanel doesn't have common parent, then you can use the var pLtree = Ext.ComponentQuery.query('treepanel[someProperty2=someValue2]')[0]; global method which returns an array of matched components. BUT make sure that you use a good component selector query (you can check if the returned array's length == 1).
Finally you need to use the pLtree.fireEvent('checkchange', ...); which is described HERE.
How can I get the element id of an item in a store range on ExtJS4 based on a property of the item? For instance, I am getting the store as follows:
var combobox = Ext.ComponentQuery.query('[xtype=mycombobox]')[0];
var items = combobox.getStore().getRange();
I want to jump to the correct item in the combobox based on a productid that a user selects elsewhere:
combobox.select(elementid);
I am just missing the logic that lets me say
elementid = items.getWhere('prodid', 'productid'); // Or however its actually done.
This is what I ended up coming up with, which actually required two seperate calls. Not sure if this is the most efficient way to do it but it seems to work.
First, I need to get the model that has a productid that equals value:
var model = combobox.getStore().findRecord('productId', value);
Then, I need to figure out what the index of that model is in the overall store:
var index = combobox.getStore().indexOf(model);
Then I can take the index and apply it to back to the combobox:
combobox.select(index);