Reputation: 1889
I am failing with Knockout select list binding when using an object as a select list value. It works fine if I use a string, but I want to bind objects.
I have a Gift object and it has a Title, Price and Company. I have a select list of companies and each company has an Id and Name. The initial selection however is not the correct in the select list.
Please see fiddle: http://jsfiddle.net/mrfunnel/SaepM/
This is important to me when binding to MVC3 view models. Though I admit it may be because I am doing things the wrong way.
If I have the following model:
public class Company
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class GiftModel
{
public Company Company { get; set; }
public string Title { get; set; }
public double Price { get; set; }
}
How do I select a Company that is bindable in my controller? Do I need to add a CompanyId property to the GiftModel and bind to that or write custom binder. Am I missing something fundamental here?
Thanks in advance.
Upvotes: 1
Views: 7652
Reputation: 1
To make an object observable, use the foeach binding. If you have such a scenario:
var model = {
myObj : ko.observable();
}
if you try to bind to myObj.label it won't work:
<span><a href="#" data-bind="text: myObj.label"></a></span>
however, using the foreach binding:
<span data-bind="foreach: myObj"><a href="#" data-bind="text: label"></a></span>
ko iterates through the properties as it would through an array in the usual javascript manner and things will work.
Upvotes: 0
Reputation: 101
You need to do a lot of stuff.
An CompanyId in your ViewModel is the only way to bind and make this observable. You can not make a object observable only it´s values
<form class="giftListEditor" data-bind="submit: save">
<!-- Our other UI elements, including the table and ‘add’ button, go here -->
<p>You have asked for <span data-bind="text: gifts().length"> </span> gift(s)</p>
<table>
<tbody data-bind="foreach: gifts">
<tr>
<td>Gift name: <input data-bind="value: Title"/></td>
<td>Price: $ <input data-bind="value: Price"/></td>
<td>Company: <select data-bind="options: $root.companies, optionsText: 'Name', optionsValue: 'Id', value: CompanyId"/></td>
<td>CompanyId: <span data-bind="text: CompanyId"></span></td>
<td><a href="#" data-bind="click: $root.removeGift">Delete</a></td>
</tr>
</tbody>
</table>
<button data-bind="click: addGift">Add Gift</button>
<button data-bind="enable: gifts().length > 0" type="submit">Submit</button>
</form>
your model
// Fake data
var initialData = [
{ Title: ko.observable('Item 1'), Price: ko.observable(56), CompanyId: ko.observable(1) },
{ Title: ko.observable('Item 2'), Price: ko.observable(60), CompanyId: ko.observable(2) },
{ Title: ko.observable('Item 3'), Price: ko.observable(70), CompanyId: ko.observable(2) }
];
var initialCompanies = [
{ Id: 1, Name: "Comp 1" },
{ Id: 2, Name: "Comp 2" },
{ Id: 3, Name: "Comp 3" }
];
var viewModel = {
gifts: ko.observableArray(initialData),
companies: initialCompanies,
addGift: function() {
this.gifts.push({
Title: "",
Price: "",
Company: { Id: "", Name: "" }
});
},
removeGift: function($gift) {
viewModel.gifts.remove($gift);
},
save: function() {
console.log(ko.toJS(viewModel.gifts));
}
};
ko.applyBindings(viewModel, document.body);
Upvotes: 5