I'm using the Kendo UI ListView, using MVVM bindings. The definition of the listview looks like:
<tbody id="listview" data-role="listview"
data-template="ListItemTemplate" data-selectable= "true"
data-bind="source:categoriesDataSource, events:{change:onListChange}">
The rows of the listview are <tr> rows bound to the following view model:
var viewModel = kendo.observable({
categoriesDataSource: new kendo.data.DataSource({
data: #(Html.Raw(JsonConvert.SerializeObject(Model.ItemCategories)))
})
});
I'm converting the array of JSON objects directly; this works out great. However, I also have a change event defined and that gets executed correctly, but I don't know how to grab the values of the currently selected record. Is there a way to get that from the underlying data source? I was trying the following event handler in the view model, which the code runs but the values are not of the selected record:
onListChange: function(e) {
this.set("ID", e.data.ID);
this.set("ParentItemCategoryTypeID", e.data.ParentItemCategoryTypeID);
this.set("Code", e.data.Code);
this.set("Name", e.data.Name);
this.set("IsActive", e.data.IsActive);
this.set("Sequence", e.data.Sequence);
}
How do I get the values of the currently selected record?
Take a look at this I made for u
onListChange: function(e) {
var index = e.sender.select().index();
var item = e.sender.dataSource.view()[index];
console.log(item); // item here is the currently selected list item (ObservableObject))
}
There is dataItem method to get the data item specified for kendo widgets.
http://docs.telerik.com/kendo-ui/api/javascript/ui/listview#methods-dataItem
onListChange: function(e) {
console.log(e.sender.dataItem(e.sender.select()));
}
Related
In the Kendo UI documentation for the DataSource component, it states that the data function is used to get data items for the data source.
However it also states that if the data source is bound to a JavaScript array (via the data option) the data method will return the items of that array. Every item from the array is wrapped in a kendo.data.ObservableObject or kendo.data.Model.
How can I retrieve the original unwrapped data items (i.e. having same reference) that were passed into the data source?
I ask because I'm using a Kendo UI treeview control and in its event handlers (e.g. check event) I want to update the original data item for a tree node based on some custom logic.
Update
For example here is a simple treeview having a single node (of course in a realistic scenario the tree would contain many nodes) . When checking the node I want to get a reference to the original data item for the checked node. this.dataItem(e.node) does not return the original data item as the log statement outputs false.
<div id="treeview"></div>
<script>
var mydata = [
{ text: "foo", checked: false}
];
$("#treeview").kendoTreeView({
checkboxes: true,
dataSource: mydata,
check: function(e) {
console.log(this.dataItem(e.node) == mydata[0]); //I want this to output true
}
});
</script>
If I understand your question correctly, you can get to the records independently by referencing your data source and using the .at(x) function, where x equals whatever record of your data source you are attempting to access. So to get the first.
var theData = yourDataSource.at(0);
To update it, you then use .set and .sync.
theData.set('userFirstName', 'Joe');
theData.set('userAverageTime', 10);
yourDataSource.sync();
Using .set() is handy because if you store all your updates into an iterable collection, then you can just run through them.
$.each(updatedVars, function(key, element) {
theData.set(key, element);
});
yourDataSource.sync();
I have a knockout template:
<script type="text/javascript" id="myList">
// template stuff here
</script>
I call it in with the foreach option:
<div data-bind="template: { name:'myList', foreach: ItemList }"></div>
I get the view model form my controller and use the following Javascript to bind it:
var viewModel = ko.mapping.fromJS(#Html.Raw(JsonConvert.SerializeObject(Model));
ko.applyBindings(viewModel, document.getElementById("contentsDetails"));
I return a few items from my controller and everything renders fine.
My problem is that if I add to my observable array
var itemToAdd = {
Name: ko.observable("name a"),
Desc: ko.observable("desc a")
}
viewModel.MyObservableArray().push(itemToAdd);
I have checked the array is observable using:
console.log(ko.isObservable(viewModel.MyObservableArray));
It does not update the UI template by adding the new item to the list.
What am I doing wrong here?
It's this line:
viewModel.MyObservableArray().push(itemToAdd);
By putting brackets after MyObservableArray, you're accessing the underlying array, and directly pushing the value into it. Knockout doesn't see this change. Instead, call .push directly on the observableArray:
viewModel.MyObservableArray.push(itemToAdd);
This is a method in knockout that will update the underlying array and notify any subscribers of the change, and will result in the UI being updated.
Alternatively, you can keep it as you have it, but inform knockout that it has changed, which will trigger the updates:
viewModel.MyObservableArray().push(itemToAdd);
viewModel.MyObservableArray.valueHasMutated();
I have a data table with checkbox selection. If an item in the table is checked I want to display that data in another part of the page. Seems like it should be simple but I can't seem to figure it out. I made a js
JS Bin with data table example
Here is the controllers/route
App.IndexController = Ember.Controller.extend({
productLinks: function(){
return this.get('content');
}.property('model', 'isSelected'),
selectedProduct: function(){
var selectedProd = this.get('productLinks').filterBy('isSelected', true);
return selectedProd[0];
}.property('isSelected'),
isSelected: null
});
I would like this to evolve to only allowing a single selection, but I'll address that once I can get the data to display.
You need to define the dependency (property) correctly. You have the computed property depending on the isSelected property on the controller itself. You need to make it dependent on the isSelected property on each member of productLinks, which you do with the #each syntax.
selectedProduct: function(){
var selectedProd = this.get('productLinks').filterBy('isSelected', true);
return selectedProd[0];
}.property('productLinks.#each.isSelected')
I'm updating multiple properties on a Kendo datasource row model (using model.set javascript), and I want the grid to update only after the last change is made.
Another issue is that i don't know (without many if statements) whether any of the properties actually changed.
This is the answer I pulled off the Kendo Forum:
var grid = $("#grid").data("kendoGrid");
grid.bind("dataBinding", function(e) { e.preventDefault(); });
//begin modifying the data
//.....
//finish modifying the data
grid.unbind("dataBinding");
grid.refresh();
Question:
How can I get list of nested views (as they are defined in template) and reorder them? Or move view from one parentView to another?
For example, I'd like to switch places column with date and column with image, or hide any of them on user action
{{#data-grid}}
{{#grid-column}}
{{format-date date}}
{{/grid-column}}
{{#grid-column}}
{{#link-to 'somewhere'}}<img scr="i.png" title="hello"/>{{/link-to}}
{{/grid-column}}
{{/data-grid}}
Reason:
I'm implementing datagrid with reordering and hiding collumns in runtime. Declaring view classes for all cases and then using them in controller seems ugly to me.
Already tried to use ContainerView but could not find the way to fill childViews with template contents
UPDATE
Source code of data grid in current state: http://pastebin.com/E61e6WCt
If you want to implement this yourself, you should have a look at the CollectionView. Each of your columns should be one item in the content array of your view. Reordering the array should also reorder the DOM elements correctly.
Here is a rough sketch: Basically you are overriding createChildView within your subclass. You could pass strings into the content array indicating their type. Within createChildView you then can access the current item via the attrs object and its content property.
App.ColumnsCollectionView = Ember.CollectionView.extend({
content : ["date", "image"],
createChildView: function(viewClass, attrs) {
var itemFromContent = attrs.content; // is either 'date' or 'image'
if (itemFromContent == 'date') {
viewClass = App.YourDateColumnView;
} else {
viewClass = App.YourImageColumnView;
}
return this._super(viewClass, attrs);
}
});