Does kendo ui support nested Datasources?
I have a table within which I need one of the columns to have a nested table. I am not using json to populate either.
In whatever little documentation I've been able to find it says that nested datasources arnt supported but those use json.
If someone could provide an example of how to implement this, it would be very helpful.
short answer: yes, the HierarchicalDataSource is just am immplementation of the normal datasource that nests. in other words each "node" is a instance of a datasource.
Kendo API Doc
there isn't a ton of documentation of how the HierarchicalDataSource works; I personally had to mess around a lot in the source code to get a handle on it. Kendo only uses it for the treeview and it seems to be built specifically for it. However, You can more or less get it behave how you want by altering the Node model passed into it.
You cannot just use this dataSource with any widget, the widget needs to support it internally. I personally had to create my own listview implemenation to work with it because i wanted nested CRUD .
This is a simple listview implementation that covers a nested template. While is not perfect it seems to be the simplest way to manage this challenge. I would also suggest that the question lacks clarity. I am reaching to answer what I believe to be the obstacle.
// Parent ListView
<div id="parent-listview"></div>
// Parent template
<script id="parent-template" type="text/x-kendo-template">
<a>#=ParentDescription#</a>
// Child ListView
<div id="child-listview-#=Id#"></div>
</script>
// Child template
<script id="child-template" type="text/x-kendo-template">
<a>#=ChildDescription#</a>
</script>
// Bind Parent
$("#parent-listview").kendoListView(
{
template: $("#parent-template").html(),
data : parentData
dataBound: function(e) {
// Bind children
$.each(this.dataItems(), function(idx, item) {
bindChildListView(item);
})
}
});
// Bind each child item
function bindChildListView(data) {
$("#child-listview-" + Id).kendoListView({
template: $("#child-template").html(),
dataSource: data.ChildItems
})
}
NOTE I have a simple int property called Id on my data objects but you can use the uid of the row if you need to or something else.
Related
I've looked at this:
http://knockoutjs.com/documentation/extenders.html
The issue is that I'm using fromJs to create my view model, so my observerables already exist. I would think I could do the following to add an extender:
var data = result.Data;
if (!window.vmRealTimeActivity) {
window.vmRealTimeActivity = ko.mapping.fromJS(data, mappingKeys);
ko.applyBindings(vmRealTimeActivity, $('#second-btm')[0]);
} else {
ko.mapping.fromJS(data, vmRealTimeActivity);
}
vmRealTimeActivity.MyExistingObservable.extend({ numeric: null });
vmRealTimeActivity.MyExistingObservable(9999); // doesn't call numeric extender
My extender gets called the first time the extender is attached, but not after trying to change the value.
I read another SO post that stated that .extend() creates a new observerable so you have to do this, but this doesn't work either:
vmRealTimeActivity.MyExistingObservable = vmRealTimeActivity.MyExistingObservable.extend({ numeric: null });
In addition to not calling my formatter a second time, the value starts coming back NaN.
How do I attach an extender the proper way to an existing observable?
Since you are using the mapping plugin, you could specify a create callback. If you add the following to the existing mappingKeys, it would probably work (I don't know your exact mapping, so you might need to change bits here and there):
'MyExistingObservable': {
create: function(options) {
return new ko.observable(options.data).extend({ numeric: null });
}
}
This result in an extended observable upon mapping from yor data.
Here's a jsFiddle with a working example (vm1) and your current non-working example (vm2) for comparison
The above answer is correct, but for anyone interested, I found the simpler approach is to just create your view models client side and use fromJs to refresh them rather than both create and refresh them. You can then apply the answer here to support adding extend to both your parent and child view models: Map JSON data to Knockout observableArray with specific view model type
With either approach you will have to create additional mappings.
I have a number of instances where my Kendo Datasource <-> Backbone connection is working as expected, but I have run into a situation that I hope someone knows more about.
When a model or collection is synced from the server, the datasource is also updated and respective Kendo controls are also updated.
However, if you already have a collection loaded, and you loop through that collection, making a change to the models in that collection, it appears that the linked DataSource is not getting the changes.
Example:
I have a collection of "tags" that are displayed as checkbox options. I want to display some of those checkboxes as "checked" based on other data coming from the server (in this case, I am loading a product - and want to display what colors are selected):
this.colors.each(function (me) {
me.set('selected', '');
if ( _.findWhere(self.model.get('colors'), {id: me.id} ) ) {
me.set('selected', 'checked');
};
})
$('#colors').kendoListView({
dataSource: this.colors_datasource,
template: '<div class="checkbox"><input type="checkbox" value="#: id #" #:selected#> #: name #</div>'
});
The 'this.colors_datasource' is defined in the initialize method of this backbone view. It is not seeing these changes being made to the backbone models in the collection "this.colors". I presume that this is because the models are not syncing to the server.
If I add the definition between these two blocks of code, it works:
this.colors.each(function (me) {
me.set('selected', '');
if ( _.findWhere(self.model.get('colors'), {id: me.id} ) ) {
me.set('selected', 'checked');
};
})
this.colors_datasource = new kendo.Backbone.DataSource({
collection: this.colors
});
$('#colors').kendoListView({
dataSource: this.colors_datasource,
template: '<div class="checkbox"><input type="checkbox" value="#: id #" #:selected#> #: name #</div>'
});
So, my question: Is this the only solution, or is there a way to tell an already defined DataSource to rebuilt itself?
Thanks - StackOverflow Rocks!
I'm guessing there is a timing issue. Perhaps, in the case where it's not working, the datasource is being initialized incorrectly?
The code you provided at the bottom is how you should do it. From the docs you can read the kendo.Backbone.DataSource is providing the magic to get the 2-way binding. Without this the kendo ui does not know about the change events coming from the backbone collection. They provide sample code there that's very similar to what you've suggested here.
I also wanted to comment on this line:
I presume that this is because the models are not syncing to the server.
One of the beautiful things about the Backbone.Events system: it does not require a round-trip to the server in order for the UI to keep in sync with changes. As long as you handle the basic collection events add, remove, change, etc. you can keep your interface up to date without talking to your server.
I am trying to disable option items in a dijit/Form/FilteringSelect control that is populated using a store.
Following this guide: http://dojotoolkit.org/documentation/tutorials/1.9/selects_using_stores/
It seems to be only possible if the Select control was created without using a store. I have deduced this from debugging the FilteringSelect example. I have tried two methods to disable an item:
Following the advice in this thread: How to disable a single option in a dijit.form.Select?. However, the "stateStore" store object in the FilteringSelect example does not have an 'options' property.
Attempting to access the appropriate element in the store object. For example, in the FilteringSelect example, I do the following:
var optionItem = stateStore.get("AZ");
optionItem.disabled = true;
stateStore.put(optionItem);
select.startup();
Neither method seems to work, so it seems that the only way to have disabled items in Dijit Select controls is to use the options property instead.
Thanks in advance for a solution!
There is a difference between the data in your store (which is in fact the business data) and your rendered data (containing view logic). If you use a store, you're actually feeding your rendered data with your store.
To alter the rendered data (= the options in your select), you need to use the getOptions(idx) method of the dijit/form/Select as you can read in the API documentation. To alter the disabled state of the option you can use:
registry.byId("mySelect").getOptions(myId).disabled = true;
That's all you need. Changing the store data won't help, since it represents business data, not view data. I also made an example JSFiddle where the second option is disabled.
for dojo 1.10 and upto 1.x latest version, you need to add a line of code to update the selection UI:
registry.byId("mySelect").getOptions(myId).disabled = true;
registry.byId("mySelect").updateOption(myId);
Using http://www.lukemelia.com/blog/archives/2012/03/10/using-ember-js-with-jquery-ui/ I'm trying to implement a sortable list in a template loaded by an Ember.ArrayController which has an array of Phonenumbers as content :
{{#collection App.SortableListView contentBinding="phonenumbers" itemViewClass="App.SortableItem"}}
<b>{{phonenumber.cost}}</b>
{{/collection}}
I'm trying to update the 'order' property of each phonenumber after a sort but I can't figure out how to do that :
App.SortableListView = JQ.SortableListView.extend({
items: 'article',
//update is a jquery ui method called when the sort ends and dom has been updated
update: function(event, ui) {
// I would like to update and persist each phonenumbers model here
}
});
I have tried various things : bindAttr on order, data attributes through jquery, using the contentIndex property of each childView (but it's not updated when sorting)... Everything failed, or was too much complexity for such a simple thing.
I guess I'm missing something obvious, thx for your help.
There is sortProperty method on array controller that do what you want
I've inherited a project which uses Knockout.JS to render a listing of posts. The client has asked that this listing be paginated and I'm wondering if this is possible and appropriate using Knockout.JS. I could easily achieve this in pure JavaScript but I'd like to use Knockout (if appropriate) for consistency.
From what I can tell, the page uses a Native Template in the HTML of the page. There is a ViweModel which stores the posts in a ko.ObservableArray() and a post model.
The data is loaded via a jQuery ajax call where the returned JSON is mapped to post model objects and then passed into the ObservableArray which takes care of the databinding.
Is it possible to amend the ViewModel to bind pagination links (including "previous" and "next" links when required) or would I be better off writing this in plain JS?
It should be easy enough to build a computed observable in knockout that shows a "window" of the full pagelist. For example add to the view model:
this.pageIndex = ko.observable(1);
this.pagedList = ko.computed(function() {
var startIndex = (this.pageIndex()-1) * PAGE_SIZE;
var endIndex = startIndex + PAGE_SIZE;
return this.fullList().slice(startIndex, endIndex);
}, this);
Then bind the "foreach" binding showing the record to pagedList instead of the full list, and in the forward and back links, simply change the value of pageIndex. Starting from there, you should be able to make it more robust/provide more functionality.
Also, this assumes you preload all data to the client anyway. It's also possible to make JSON calls on the previous and next link and update the model with the returned items. The "next" function (to be added to the view model prototype), could look like this:
ViewModel.prototype.next = function() {
var self = this;
this.pageIndex(this.pageIndex()+1);
$.ajax("dataurl/page/" + this.pageIndex(), {
success: function(data) {
self.dataList(data);
}
});
}
(using jQuery syntax for the ajax call for brevity, but any method is fine)
Writing features in KO always tend to generate less code and cleaner code than doing the same in "plain JS", jQuery or similar. So go for it!
I implemented a combobox with paging like this
https://github.com/AndersMalmgren/Knockout.Combobox/blob/master/src/knockout.combobox.js#L229
In my blog post, I have explained in very detail how to do it. you can find it (here. http://contractnamespace.blogspot.com/2014/02/pagination-with-knockout-jquery.html). It's very easy to implement and you can do it with a simple JQuery plugin.
Basically, I have used normal knockout data binding with AJAX and after data has been retrieved from the server, I call the plugin. You can find the plugin here. its called Simple Pagination.