I'm trying to fetch the children data item of the selected node of a Kendo Treeview. I used this as my reference: http://www.telerik.com/forums/children-of-dataitem
Here are the excerpt of my code:
<ul id="fileTreeView">
</ul>
var fileTreeView = $("#fileTreeView").kendoTreeView({ template: kendo.template($("#treeview-template").html()) }),
ftvData = fileTreeView.data('kendoTreeView'),
selectedNode = ftvData.select(),
items = ftvData.dataItem(selectedNode).children.data;
I assumed e.node from the link above has similar data type with the ftvData.select(). So when selectedNode.hasChildren is true, I expected that items has value but the items.length stays as 0.
Anyway, I'm just trying to prevent the creation of duplicate "folder".
It looks like children.data is just an empty shell. What works is children._data. Looks like it is a bug with version we're using: telerik.ui.for.aspnetmvc.2015.1.408.commercial
Related
I currently have an iron-list within another iron-list. The parent's data comes from a firebase-query element, and the child's data is computed from each parent item. The db structure and code looks a bit like this:
DB: [
category1: [
itemId1: {
price: 10,
title: "title"
}
]
]
<iron-list id="categoryList" items="{{categories}}" multi-selection as="category">
<template>
<div class="category-holder">
<iron-list id="{{category.$key}}" items="{{_removeExtraIndex(category)}}" as="item" selection-enabled multi-selection selected-items="{{selectedItems}}" grid>
<template>
<div class$="{{_computeItemClass(selected)}}">
<p>[[item.title]]</p>
<p>[[item.price]]</p>
</div>
</template>
</iron-list>
</div>
</template>
</iron-list>
After selecting any number of items, the user can tap on a fab to batch edit the price. This is where I'm having issues. I can't figure out how to access the correct child iron-list in order to call list.set...I'm currently trying the following very nasty method:
var categories = this.$.categoryList;
var categoryItems = categories.items;
(this.selectedItems).forEach(function(item) {
var index = item.itemId;
categoryItems.forEach(function(itemList, categoryIndex) {
if (itemList[index]) {
categories.set('item.' + categoryIndex + '.price', 10);
}
}, this);
}, this);
I'm iterating over the selected items in order to extract the item index and then iterating over the parent iron-list data (categoryItems) in order to check if the given item exists in that subset of data. If so, then I use the category index and attempt to call set on the parent iron-list using the given path to access the actual item I want to edit. As expected, this fails. Hopefully I've made myself clear enough, any help would be appreciated!
EDIT #1:
After much experimenting, I finally figured out how to correctly mutate the child iron-list:
(this.selectedItems).forEach(function(item) {
var list = this.$.categoryList.querySelector('#' + item.category);
var index = list.items.indexOf(item);
list.set(["items", index, "price"], 30);
}, this);
A couple of things worth noting. I'm using querySelector instead of the recommended this.$$(selector) because I keep running into a "function DNE" error. But now I have another problem...after calling the function, the value gets updated correctly but I get the following error:
Uncaught TypeError: inst.dispatchEvent is not a function
Here's a picture of the full error message:
I see the light, hopefully someone can help me out!
OK, I'll take a shot at this. I think the following happens, and I guess this based on how dom-repeat works:
var categories = this.$.categoryList;
var categoryItems = categories.items;
You take the variable that the iron-list is based on, but setting one array to another just creates a reference in javascript. As soon as you update categoryItems, you also update this.$.categoryList.items. When you later sets the new value, iron-list will do a dirty check and compare all subproperties, and because they are equal (because ... reference), the iron-list wont update the dom.
What you should do is to make sure it's a totally new copy and the way of doing that is to use JSON.parse(JSON.stringify(myArray)).
Further on, one major flaw I see in your code is that you're using querySelector to select an element, and then manipulate that. What you should do is to use this.categories and only that variable.
So your method should look something like:
// Get a freshly new array to manipulate
var category = JSON.parse(JSON.stringify(this.categories);
// Loop through it
category.forEach(category) {
// update your categoryList variable
}
// Update the iron list by notifying Polymer that categories has changed.
this.set('categories', category);
I am having a problem to display header tooltip on angular-ui-grid.
Here is plunker demo.
Any idea how to make it work?
I have not been able to figure out how to make the directive work properly internally by setting the headerTooltips as strings. The directive developers are making it work using a different implementation than yours that can be seen in this Plunker.
This solution will patch the problem until a better or more permanent one can be found. Place it at the end of your service call inside of your controller like the following.
upareneStavkePromise.then(function(upareneStavkeData){
$log.debug(upareneStavkeData);
$scope.ucitaniUpareniPodaci = true;
$scope.gridOptionsUpareniPodaci.data = upareneStavkeData.grupe;
upareneStavkeTotals = upareneStavkeData.totals;
/*
* Patch for possible bug:
* Description: Setting headerTooltip property
* value as a string doesn't render the value at
* runtime.
*
*/
//class for the header span element
var headerClass = ".ui-grid-header-cell-primary-focus";
//the column definitions that were set by the developer
var colDefs = $scope.gridOptionsUpareniPodaci.columnDefs;
//Get the NodeList of the headerClass elements.
//It will be an array like structure.
var headers = document.querySelectorAll(headerClass);
//loop through the headers
angular.forEach(headers,function(value,key){//begin forEach
//Set the title atribute of the headerClass element to
//the value of the headerTooltip property set in the columnDefs
//array of objects.
headers[key].title = colDefs[key].headerTooltip;
});//end forEach
/****************END PATCH********************/
});
I'm using Backgrid and I create the Backgrid Object as follows in my Controller:
$.when(recipeRequest).done(function (recipes) {
List.grid = new Backgrid.Grid({
columns: columns, // where columns is defined elsewhere
collection: recipes // recipes is the result of a fetch
})
// Then add it to the Marionette template
}
The above works perfectly and items display as expected
Once the table is displayed we are providing filtering functionality ServerSide as follows:
filterRecipes: function (query) {
// remove any incomplete network requests
_.each(RecipeManager.fetchXhrs, function (r) {
r.abort()
})
// get a filtered set of recipes
var filteredRecipes = RecipeManager.request('recipe:entities', query)
$.when(filteredRecipes).done(function (recipes) {
// this line shows that the result set is being updated as expected with for example 6 results
console.log(recipes)
// setting the new recipe result set to the grid.collection
List.grid.collection = recipes
// here the table rerenders but there are a LOT more results on the table - not 6 as expected
List.grid.render()
})
}
I'm expecting the table to be repopulated with the new collection once the results are returned but my table still shows all the old records.
I'm following the example written here How would I refresh a Backgrid table with new data? So it should redraw the table once the collection has been reset? Or do I need to empty the table first? Any ideas where I might be going wrong?
From backgridjs
Fully reactive. Relevant parts of the grid re-renders automatically upon data changes.
I have not gone through annotated source code but am guessing rerendering is tied to collection events. So, you do not need to explicitly call the render method.
$.when(filteredRecipes).done(function (recipes) {
// this line shows that the result set is being updated as expected with for example 6 results
console.log(recipes)
// setting the new recipe result set to the grid.collection
// considering recipes is backbone collection
// if result is array of objects then List.grid.collection.reset(recipes)
// it should re render the grid
List.grid.collection.reset(recipes.models);
})
I want to understand how to successfully set a value inside a DropDown List after it has been populated by a promise. The value to be set will be taken from another promise which will fill a form with a JSON structure.
In my particular case the incidence is as follows
The Drop-Down List is built as :
1) HTML Template (Jade)
select(name="inputUserRelationship",
ng-model="myForm.relationship",
ng-options="relationshipOption as relationshipOption.value for relationshipOption in relationships track by relationshipOption.id",
ng-init="myForm.insuredRelationship = relationships[0]")
option(value="") -- SELECT --
2) Controller:
$scope.getRelationTypes = function(){
HttpSrv.get('api/getRelationTypes/').then(function(results){
$scope.relationships = results;
}); };
The form gets filled in the Controller as follows:
$scope.getFormInformation = function(ID){
HttpSrv.get('/api/getFormInfo/' + ID).then(function(results){
if(results)
{
$scope.fillForm(results);
}
}); };
$scope.fillForm = function(filledFormData){
$scope.myForm.relationship = filledFormData.relationnshipID; };
This produces the following issues on my JS Debugging Console:
The value gets set on the model
The Drop-Down List stays on the default empty value ([0]).
When I try to change the selected option on my Drop-Down list it then produces the following JS Console Error.
TypeError: Cannot assign to read only property 'id' of 9
at setter (vendor.js:42989)
at Lexer.readIdent.token.fn.extend.assign (vendor.js:42424)
at validationErrorKey.$setViewValue (vendor.js:49629)
at vendor.js:53523
at Scope.promises.$get.Scope.$eval (vendor.js:44729)
at Scope.promises.$get.Scope.$apply (vendor.js:44827)
at HTMLSelectElement. (vendor.js:53465)
at HTMLSelectElement.jQuery.event.dispatch (vendor.js:4641)
at HTMLSelectElement.jQuery.event.add.elemData.handle (vendor.js:4309)
Any information is greatly appreciated. I have already researched & tested the $scope.apply() and $q options and neither have been successful to me even though I know they point to the right direction.
Cheers!
if your $http API call returns an json in the format:
[{"id":"1", "value":"Dropdown desc"}, {...}, {}]
You should set an object literal with the same structure to set the dropdownlist to a specific values like:
$scope.myForm.relationship = {"id":"1", "value":"Dropdown desc"};
When adding a rows to a grid, and then clicking on it, it gets selected (and highlighted). Then, clicking elsewhere but the new row remains highlighted (so now there are to highlighted rows).
Please, does anyone know what the problem could be? How to make it behave normally, i.e. clicking a row deselects (de-highlights) the other one?
After I reload the page (so the new row is not new anymore), everything works as expected.
Edit: Here's the code for adding rows:
var rec = new store.recordType({
test: 'test'
});
store.add(rec);
Edit 2: The problem seems to be listful: true. If false, it works! But I need it to be true so I'm looking at this further... It looks like as if the IDs went somehow wrong... If the ID would change (I first create the record and then the server returns proper ID, that would also confuse the row selector, no?)
(Note, correct as ExtJS 3.3.1)
First of all, this is my quick and dirty hack. Coincidentally I have my CheckboxSelectionModel extended in my system:-
Kore.ux.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.CheckboxSelectionModel, {
clearSelections : function(fast){
if(this.isLocked()){
return;
}
if(fast !== true){
var ds = this.grid.store,
s = this.selections;
s.each(function(r){
//Hack, ds.indexOfId(r.id) is not correct.
//Inherited problem from Store.reader.realize function
this.deselectRow(ds.indexOf(r));
//this.deselectRow(ds.indexOfId(r.id));
}, this);
s.clear();
}else{
this.selections.clear();
}
this.last = false;
}
});
And this is the place where the clearSelections fails. They try to deselect rows by using ds.indexOfId(r.id) and it will returns -1 because we do not have the index defined remapped.
And this is why we can't find the id:-
http://imageshack.us/photo/my-images/864/ssstore.gif/
Note that the first item in the image is not properly "remapped". This is because we have a problem in the "reMap" function in our Ext.data.Store, read as follow:-
// remap record ids in MixedCollection after records have been realized. #see Store#onCreateRecords, #see DataReader#realize
reMap : function(record) {
if (Ext.isArray(record)) {
for (var i = 0, len = record.length; i < len; i++) {
this.reMap(record[i]);
}
} else {
delete this.data.map[record._phid];
this.data.map[record.id] = record;
var index = this.data.keys.indexOf(record._phid);
this.data.keys.splice(index, 1, record.id);
delete record._phid;
}
}
Apparently, this method fails to get fired (or buggy). Traced further up, this method is called by Ext.data.Store.onCreateRecords
....
this.reader.realize(rs, data);
this.reMap(rs);
....
It does look fine on the first look, but when I trace rs and data, these data magically set to undefined after this.reader.realize function, and hence reMap could not map the phantom record back to the normal record.
I don't know what is wrong with this function, and I don't know how should I overwrite this function in my JsonReader. If any of you happen to be free, do help us trace up further for the culprit that causes this problem
Cheers
Lionel
Looks like to have multi select enabled for you grid. You can configure the selection model of the grid by using the Ext.grid.RowSelectionModel.
Set your selection model to single select by configuring the sm (selection model) in grid panel as show below:
sm: new Ext.grid.RowSelectionModel({singleSelect:true})
Update:
Try reloading the grid using the load method or loadData method of the grid's store. Are you updating the grid on the client side? then maybe you can use loadData method. If you are using to get data from remote.. you can use load method. I use load method to update my grid with new records (after some user actions like add,refresh etc). Or you could simply reload as follows:
grid.getStore().reload();