I'm attempting to populate a select field with options using bootstrapped data. I'm encountering an issue when binding my array of models to the jQuery select object...
The HTML
<select data-each-project="projects" id="project-selection">
<option data-value="project:description"></option>
</select>
The Binding
project_array = new Array()
_.each projects, (project) ->
projects_array.push project
rivets.bind #el.select, projects:projects_array
The Result
I receive an error indicating that the object has no .on method -> which it doesn't because it is an array of models not a model it self...
How should this really be done? Thanks!
When you subscribe to an iteration binding rivets does two things:
Subscribes to the entire array so if it changes it will rerun the
iteration
Subscribe to all children of the array that need binding
Rivets isn't subscribing to your children because you are not using any bindings that require it.
project:description = non-subscribe binding
project.description = subscribe binding
If you don't want to subscribe to array changes (I think that's what you're asking for) you can do data-each-project=":projects"
Related
I have been facing some issues regarding "foreach" binding to an ko.observableArray for knockout, specifically knockout 3.5.0. The "foreach" binding is creating 2 elements on the U.I side while in the current data context, i am only having one single object within an observableArray. i am binding it as follows:
<!-- ko foreach: { data: $root.(...my own javascript function)') } -->
...
<!-- /ko -->
What i am doing here is that i am manually adding a new entry into an empty observableArray by calling .push() on the observableArray. The entry is added successfully to the observableArray, however it will show 2 UI elements instead of one even though I am only pushing in one entry into the observableArray.
However, if i set the attribute "includeDestroyed: false", it seems that the problem will disappear.
From what i have gathered, there were a few changes in Knockout 3.5.0 that relates to the implementation of foreach binding being changed in knockout. There has been a change to the implementation of "arrayChange" which detects any changes in the knockout observable array.
What I would like to know is the exact flow of what goes on during an "arrayChange" event, and is there any way i can find out how an empty observableArray handles a "push" function
From the official Knockout github page, when looking into release changelogs you can spot the following:
To improve performance when array changes are from a known, single
operation, such as push, the foreach binding no longer filters out
destroyed items by default. To turn this off and filter out destroyed
items, you can set includeDestroyed: false in the foreach binding or
set ko.options.foreachHidesDestroyed = true to use the previous
behavior by default.
So you can either set the "ko.options" globbaly, or set the flag like you do.
For more info you can look here.
As for the flow of the event, i suggest looking into the debug version of ko 3.5, along with a debugger and coffe!
How to add the child value when we checked the parent element? How to passing Checkbox value to javascript?
I don't know the code which you have been written let me know code.
Most probably you required to create one action and call it when you checked checkbox and this action push objects into $scope.items or you can use map in javascript for faster operation while fetching.
I hava a selectOptions ajax-based asincronous loader; it accepts remote address and returns an observable array, correctly populated with descriptions and keyvalues to be accepted by the following binding
<select data-bind="value: selectedVal, options: opts, optionsText: 'desc', optionsValue:'key', optionsCaption: ''"/></div>
The fact is that, being asincronous, when I trigger a select options change, based on some user actions, I assign it to my model observable array, I do not get the select popuated, but remains empty.
mymodel.opts = loadOptions("<remoteaddress>");
I know when the second line is called the anwer is not arrived yet, but the returned value is an observableArray, so it should respond correctly whenever is populated, having been assigned to an observable array binded with the ui.
If I hardcode the returned object from the ajax call (when it returns) taking it from console.log in Firefox, or if I pass the observable array opts into the loadOptions, and change it to build up the opts inside it, then it works, but I really need to use loadOptions as is, asincronous. I also tried to append mymodel.opts.valueHasMutated(), but yet ko cannot use the newlly arrived observableArray.
If possible leaving intact the options loader, and if possible without using a custom binding, can I use the incoming observable array for binding when it will be ready?
The problem you've got is that when this line runs:
mymodel.opts = loadOptions("<remoteaddress>");
it's replacing the entire observable array with a different observableArray, rather than updating the current one. You need to update the existing one - can you change loadOptions to return a normal array, rather than an observable one? You can then do:
//clear any existing entries
mymodel.opts.removeAll();
//push the new entries in
mymodel.opts.push.apply(mymodel.opts, loadOptions("<remoteaddress>"));
I have a JSON object that I used to create a form. This JSON object is parsed by KnockoutJS.
Now, when I modify the form, I want the JSON object to be updated according to the modifications made in the form. The thing is that I don't know in advance how the form will be like but I know in the JSON Object which fields need to be updated.
I really don't know what is the best way to procede. I know that I could reconstruct the JSON Object each time something has changed but this seems like a bad idea and a tedious process.
Is there a simple way to map each JSON Object field to form items in KnockoutJS ?
Here's a JSFiddle of what I'm currently doing:http://goo.gl/ZBaV7
Update :
I realized something interesting with this line:
<input type="text" data-bind="value: $data.value, attr : { disabled: $data.disabled }" />
I'm accessing the value directly from the array via ($data.value). Is there a way in the html to say to knockout to bind to this particular attribute in the array. I know that if the array would get reordered everything would get messed up but since I know that the only thing that can changed is this property I'm ready to take this risk ?
In other words, is there a way to manually say that when this value changes to change it in the array such as
data-bind="onChange: $data.value = this.value"
Is there a simple way to map each JSON Object field to form items in
KnockoutJS ?
Yes, If I understand what you want to do correctly. As of now, the values in your view model are not observables and won't be updated automatically as the form values change. There is a plugin to handle this mapping.
http://knockoutjs.com/documentation/plugins-mapping.html
Example: Using ko.mapping
To create a view model via the mapping plugin, replace the creation of
viewModel in the code above with the ko.mapping.fromJS function:
var viewModel = ko.mapping.fromJS(data);
This automatically creates observable properties for each of the
properties on data. Then, every time you receive new data from the
server, you can update all the properties on viewModel in one step by
calling the ko.mapping.fromJS function again:
ko.mapping.fromJS(data, viewModel);
Hopefully this helps.
If your Knockout ViewModel matches your form, you could just use the built in ks.toJSON()
http://knockoutjs.com/documentation/json-data.html
A better option, especially if your form is large or complex, is to use either the mapping or viewmodel plug-ins
http://knockoutjs.com/documentation/plugins-mapping.html
http://coderenaissance.github.io/knockout.viewmodel/
The simplest way to turn your json model into a usable knockout model is with the mapping plugin.
Alternatively, you can manually copy fields from your json model into ko.observable members of your view model, which give you more control and lets you choose to skip read-only properties.
I need to know how to trigger the update for an observableArray when an observable is changed inside the observableArray.
I have an observableArray that represents a binary tree. I'm using a storage mapping function to get and set the values in the array so it has to be balance even thought it might only contain an empty observable. E.g. nodes()[9] maybe null but when that node is updated I would call nodes()[9](set new value) and need to trigger the observableArray to update
Ended up using .replace() on the observableArray
Managed to look through the code and find observableArray.replace ()
RELATED: How to replace a given index element in knockoutjs