Binding on select html control using knockout - javascript

I am working using breeze + knockout using as base hottowel template.
Using this template I am able to make some binding like:
<select data-bind="options: $parent.rolesList, value: role">
Where rolelist it's a ko.observableArray() and role it's a string property. everything it's fine with this example.
My issue begin when I try make some more complex databinding, i.e:
select data-bind="options: mycollection, optionsText: 'dictionary().name()'"></select>
In this new example mycollection it's ko.observableArray() and dictionary().name() it's "object property" plus a string property.
If I go to chrome debuger I can see that mycollection()[0].dictionary().name() has a value.
So I dont' know what I am doing wrong.
Here you are a short example( you can see that I am using just dictionary.name) http://jsfiddle.net/rolandomartinezg/BN2ZP/2/

When passing a string to optionsText, Knockout simply tries to key into your object. It does not handle nested keys or run the string as JavaScript.
However, you can instead choose to pass a function for optionsText which takes in the item as the first argument and you can return whatever value that you like.
For example, in your jsFiddle, you could define a function like:
self.getOptionText = function(item) {
return item.dictionary.name;
};
Then, bind against it like:
<select data-bind="options: myCollection, optionsText: getOptionText"></select>
In your sample from the question, then you would just do item.dictionary().name() if you are dealing with observables.

Related

Knockout JS binding element's property to another element

I am trying to bind my selected category's guid property to another ko.observable element. I need to hold that data value in order to send it to the server in a correct JSON format.
Jsfiddle
I am stucked at the binding selected category's guid value to SelectedCategoryGuid in order to appear in JSON file like
'SelectedCategoryGuid': 'guid1'
I have tried $data and $root bindings in the HTML but couldn't achieve it.
Step 1: Remove the quotes around your value data-bind. You should pass a reference to an observable here, not the name of a property.
value: Info.SelectedCategoryGuid
Now, you'll see your guid paragraph print: [object Object]. That's because it's storing the whole category, not just the Guid.
Step 2: To only store the Guid property, use the optionsValue binding. This binding works similar to the optionsText binding you've already used:
optionsValue: 'Guid'
Now things start working as intended. You'll notice the initial bla value gets cleared, because it does not appear in your data set.
Here's the two changes in a fiddle: https://jsfiddle.net/40sh1vjj/

Knockout Mapping: Why does apply bindings clear values from my nested objects?

I have a KO model with a lot of nested objects and collections of nested objects. I use the ko.mappings mapping options to make sure they get properly generated during model creation, but the value gets cleared. Trying to start with a simple drop down menu and bind objects to it:
<select id="myList" name="SelectedSurvey" id="SelectedSurvey" class="form-control"
data-bind="options: AvailableSurveys, optionsText: 'Name', value: SelectedSurvey,
optionsCaption: '-- Select Survey --'"></select>
Then, take some data, when creating a new object on the page, it works fine, but when trying to edit an existing record from the same page, the drop down value is never selected. When I check viewModel.SelectedSurvey() the value is undefined, but it only becomes undefined after I callapplyBindings()`. Why is this happening? How can I fix it?
Here is a working example: http://jsfiddle.net/6wLcr52y/3/
If you open the console and run it, you'll see the log before applyBindings() is called the full ViewModel, and the nested object SelectedSurvey() are properly komapping objects that have values, but then after it's called. SelectedSurvey() becomes undefined and as such my dropdown list never has a selected value.
The SelectedValue parameter doesn't seem to want to accept an object as a valid value. It therefore clears the SelectedValue observable as soon as you apply bindings thinking that no valid value was provided.
As a workaround, I created a solution that uses the optionsValue parameter to accept the 'Id' property as a value. This will allow you to maintain control over which survey is selected by passing in merely an 'Id' value as opposed to an entire Survey object.
This requires that you update your Knockout version to 3.4.0. Are you locked in to using 2.2.1 for any reason?
I also updated your jsfiddle to include more readable implementation of the mapping plugin. Hopefully this will fix your issue:
var ViewModel = function(data) {
var self = this;
self.AvailableSurveys = ko.mapping.fromJS(data.AvailableSurveys);
self.SelectedId = ko.observable(data.SelectedSurvey.Id);
self.SelectedSurvey = ko.pureComputed(function () {
for (i = 0; i < self.AvailableSurveys().length; i++) {
if (self.AvailableSurveys()[i].Id() === self.SelectedId()) {
return self.AvailableSurveys()[i];
}
}
})
}
Fiddle: http://jsfiddle.net/dw1284/v1L5tw6h/3/

I can't access the properties of an object even though I can see it's contents

This code used to work just fine when I was using bootstrap's way of dropdown menus.. now that I switched to conventional I dont know why I'm getting this problem. Why can't I access the properties?? Driving me nuts here
HTML
<select class="form-control" ng-model="client" ng-change="clientSelect(client)">
<option value="">--- Please Select ---</option>
<option ng-repeat="client in clientList" value="{{client}}">{{client.clientName}}</option>
</select>
Angular/Javascript
$scope.clientSelect = function (client) {
console.log(client);
console.log(client.clientName); //is undefined
console.log(client.clientId); //is undefined
}
Ouput:
{"clientId":102,"clientName":"Testing"} //i clearly see the properties here...
UsersController.js:130 undefined
UsersController.js:131 undefined
EDIT: when I console.log($scope.clientList) it's fine.. the object of the first item in the array looks like this:
0: Object
$$hashKey: "object:254"
clientId: 102
clientName: "Testing"
_proto: Object
You can't access properties, because the client you get from ng-repeat is a string.
Check the console log of this Plunker I created with your code. You will see that the first consol.log(client) is actually logs out this string: {"clientId":102,"clientName":"Testing 1"}. Therefore, it doesn't have any properties.
From the select docs:
Note that the value of a select directive used without ngOptions is always a string. When the model needs to be bound to a non-string value, you must either explictly convert it using a directive (see example below) or use ngOptions to specify the set of options. This is because an option element can only be bound to string values at present.
Consider using the ngOptions directive instead of <select> with ng-repeat.

Bind optionsText to property with an array of objects using Knockout?

I have an array of objects stored inside an observableArray in Knockout.js, and I'm trying to bind one of the properties of the objects to the optionsText binding for a select element, however, this isn't working an the options are not being displayed.
The observableArray is initially blank and is populated by a AJAX request:
self.currentPeople = ko.observableArray([]);
Following the AJAX request, I can console.log this and receive the following back:
console.log(self.currentPeople);
// Produces [Object, Object] where each of the objects have properties of `personId` and `personName`
Yet my select dropdown remains unpopulated:
<select class="large-3" data-bind="options: currentPeople, optionsText: 'personName', optionsValue: 'personId', optionsCaption: 'All', value: currentPerson"></select>
Only the 'All' appears. Any ideas?
If console.log(self.currentPeople) shows your array of objects, that means you're (incorrectly) populating it using assignment instead of calling it as a function.
Populate it as:
self.currentPeople(newData);

select default value using knockout

I have defined my select as below
<select id="selProductType" data-bind="options: productType , value: editProductType , optionsText: 'Name'" />
Below is my code to fill the select in my view model
// Loading combobox with Product Types
$.getJSON("../RestService/Product/AllProductTypes",
function (allData) {
var mappedProductType = $.map(allData, function (item) {
console.log(item.Id + ' ' + item.Name);
return new productType(item);
});
self.productType(mappedProductType);
});
When i initialise page i want to set default value to select. So i tried below
self.editProductType(4);
But it gives me TypeErrror saying object 4 has no method Id.
How to go about it. I have also gone through similar post in stackoverflow but no luck.
Knockout JS binding initial/default value of dropdown (select) list
If you don't specify the :
optionsValue: 'Id'
in data-bind, the binding value in this case must be an object in productType array.
You can select the default object:
self.editProductType(self.productType()[2]);
What is optionsValue?
Similar to optionsText, you can also pass an additional parameter called optionsValue to specify which of the objects’ properties should be used to set the value attribute on the elements that KO generates. You can also specify a JavaScript function to determine this value. This function will receive the selected item as its only argument and should return a string to use for the element’s value attribute.
Typically you’d only want to use optionsValue as a way of ensuring that KO can correctly retain selection when you update the set of available options. For example, if you’re repeatedly getting a list of “car” objects via Ajax calls and want to ensure that the selected car is preserved, you might need to set optionsValue to "carId" or whatever unique identifier each “car” object has, otherwise KO won’t necessarily know which of the previous “car” objects corresponds to which of the new ones.
read more at: http://knockoutjs.com/documentation/options-binding.html

Categories