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();
Related
I am trying to get a json object by an ajax call, and put it into a knockout observable.
var self = this;
this.arnVal = ko.observableArray([]);
var promise = $.getJSON('../../url/to/my/api');
promise.done(function(data) {
console.log(data);
console.log(data["metricValues"]);
self.arnVal().push(data["metricValues"]);
console.log(self.arnVal());
});
The expected values are getting printed correctly by the console logs inside the promise.done() function call. That is, the data is in the correct Array format expected by the Oracle Jet component I am binding it with.
This code is in a Knockout component javascript file, which I am using in a HTML file somewhere else as a part of a Knockout component.
In the HTML file of the component, I am using arnVal to populate a Oracle Jet chart.
But the chart never gets populated with the updated arnVal data as obtained from the getJSON call.
What am I doing wrong?
Just remove the extra parens from self.arnVal().push(...).
self.arnVal.push(data["metricValues"]);
Currently the parens are unboxing the observable array and pushing the new item to the underlying javascript array. This bypasses knockout's event triggers.
Remove the parenthesis here:
self.arnVal().push(data["metricValues"]);
//^^ here
See the spec: http://knockoutjs.com/documentation/observableArrays.html
var myObservableArray = ko.observableArray(); // Initially an empty array
myObservableArray.push('Some value'); // Adds the value and notifies observers
The reason is self.arnVal is an observable array while self.arnVal() is a simple array (which does not have notification capabilities).
I am using the datatables from YUI 2.8.2 and its widgets to edit a datasource (YAHOO.example.Data.response) as follows:
this.bpDataSource = new YAHOO.util.DataSource(YAHOO.example.Data.response);
response_datasource = this.bpDataSource;
this.bpDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
this.bpDataSource.responseSchema = {
resultsList: "item_evaluacion",
fields: [ ... ]
};
this.standardSelectDataTable = new YAHOO.widget.ScrollingDataTable("div_item",
bpColumnas, this.bpDataSource, {height:"9em"} );
I want to retrieve the edited data from this datatable and proccess it. I tried a variable pointing to this.bpDataSource first but this variable contains only the original datasource without the changes the user made.
How can I retrieve the updated version of my datasource?
The DataSource only retrieves the data but does not keep a reference to the data retrieved. Once it has passed the retrieved data to whatever requested it, in this case DataTable, it forgets about it. DataTable then keeps the data in the RecordSet collection, which is composed of individual Record instances where you can fetch the values by field name. For some funny reason, the API docs for both Record and RecordSet are not under DataTable. I know the docs for those two are somewhere in there, but they somehow got filed under some other component.
Anyway, in DataTable, you have method getRecord() which takes an index. You can loop through it until it returns null or undefined. Otherwise, I believe you could do getRecordset().getLength() and use that to iterate with a for loop. Then, on each record instance, method getData() takes the column key and returns the value.
For more information read the two 'Working with the DataTable widget' articles referenced in the heading of DataTable.
I have the following html that is bound to an object containing id and status. I want to translate status values into a specific color (hence the converter function convertStatus). I can see the converter work on the first binding, but if I change status in the binding list I do not see any UI update nor do I see convertStatus being subsequently called. My other issue is trying to bind the id property of the first span does not seem to work as expected (perhaps it is not possible to set this value via binding...)
HTML:
<span data-win-bind="id: id">person</span>
<span data-win-bind="textContent: status converter.convertStatus"></span>
Javascript (I have tried using to modify the status value):
// persons === WinJS.Binding.List
// updateStatus is a function that is called as a result of status changing in the system
function updateStatus(data) {
persons.forEach(function(value, index, array) {
if(value.id === data.id) {
value.status = data.status;
persons.notifyMutated(index);
}
}, this);
}
I have seen notifyMutated(index) work for values that are not using a converter.
Updating with github project
Public repo for sample (not-working) - this is a really basic app that has a listview with a set of default data and a function that is executed when the item is clicked. The function attempts to randomize one of the bound fields of the item and call notifyMutated(...) on the list to trigger a visual updated. Even with defining the WinJS.Binding.List({ binding: true }); I do not see updates unless I force it via notifyReload(), which produces a reload-flicker on the listview element.
To answer your two questions:
1) Why can't I set id through binding?
This is deliberately prevented. The WinJS binding system uses the ID to track the element that it's binding to (to avoid leaking DOM elements through dangling bindings). As such, it has to be able to control the id for bound templates.
2) Why isn't the converter firing more than once?
The Binding.List will tell the listview about changes in the contents of the list (items added, removed, or moved around) but it's the responsibility of the individual items to notify the listview about changes in their contents.
You need to have a data object that's bindable. There are a couple of options:
Call WinJS.Binding.as on the elements as you add them to the collection
Turn on binding mode on the Binding.List
The latter is probably easier. Basically, when you create your Binding.List, do this:
var list = new WinJS.Binding.List({binding: true});
That way the List will call binding.as on everything in the list, and things should start updating.
I've found that if I doing the following, I will see updates to the UI post-binding:
var list = new WinJS.Binding.List({binding: true});
var item = WinJS.Binding.as({
firstName: "Billy",
lastName: "Bob"
});
list.push(item);
Later in the application, you can change some values like so:
item.firstName = "Bobby";
item.lastName = "Joe";
...and you will see the changes in the UI
Here's a link on MSDN for more information:
MSDN - WinJS.Binding.as
Regarding setting the value of id.
I found that I was able to set the value of the name attribute, for a <button>.
I had been trying to set id, but that wouldn't work.
HTH
optimizeBindingReferences property
Determines whether or not binding should automatically set the ID of an element. This property should be set to true in apps that use Windows Library for JavaScript (WinJS) binding.
WinJS.Binding.optimizeBindingReferences = true;
source: http://msdn.microsoft.com/en-us/library/windows/apps/jj215606.aspx
I have a following code that fetches data from the server and add to the collection.
// common function for adding more repos to the collection
var repos_fetch = function() {
repos.fetch({
add: true,
data: {limit:curr_limit, offset:(curr_offset*curr_limit)},
success:function() {
curr_offset++;
console.log(repos.length);
}
});
};
each time I call the function "repos_fetch", the data is retrieved from the server and added to the collection "repos".
My problem is that I want to APPEND to the collection, instead of REPLACING. So I put the option "add: true" there.
But below function looks like it's keep replacing the data in collection.
What's even strange is that if I remove the line "curr_offset++;" then the data gets appended!. "curr_offset" just increments, so I get different sets of data.
What's going on here?
I've created a Source object and configured (via the creator) so that it renders a set of data for my users to order as they wish. This is all working fine. However, I cannot figure out how to retrieve the data once the user has re-ordered it. getAllNodes returns the dom nodes; I need the original data objects.
It is really easy — just use getItem() (described in the official documentation). Something like that will give you all data elements in order:
var source = new dojo.dnd.Source(...);
...
var orderedDataItems = source.getAllNodes().map(function(node){
return source.getItem(node.id).data;
});
That's it.