Reputation: 6540
I have the following observable array:
self.Profiles =ko.observableArray( ko.utils.arrayMap(initialData, function (profile) {
return {
StartDate : formatDateOnly(profile.StartDate),
EndDate : formatDateOnly(profile.EndDate),
ProfileID :profile.ID,
ProfileName : profile.Name,
ProjectName : profile.ProjectName,
ReadingListID : profile.ReadingListID,
ReadingListName : profile.ReadingListName
};
}));
I want to bind a dropdown to the profiles to show the profile names, if the value of the drop down changes then I want to update span elements with the new corresponding values to the selected profileID.
<table id="readingListApplyToProfile" class="fullWidthTable">
<tr>
<td>
Profile:
</td>
<td>
<select id="cboProfile" name="cboProfile" data-bind="options: Profiles, optionsText: 'ProfileName', 'optionsCaption': 'Select profile...', optionsValue:'ProfileID'"></select>
</td>
</tr>
<tr>
<td>
End Date:
</td>
<td>
<span data-bind="'text':EndDate"></span>
</td>
</tr>
</table>
I cannot get the spans to update because the span elements are unaware of the dropdowns value, can anyone help me please. I am totally lost.
Upvotes: 1
Views: 1621
Reputation: 3842
I had the idea of a computedObservable that takes in a ProfileID and outputs the Profile corresponding to that ID, and then binding the spans to the various properties of the outputted object. Surprisingly, it worked. I was messing around with Sujesh Arukil's fiddle to try my idea so the model is very similar.
Working example showing multiple spans: http://jsfiddle.net/jonhopkins/fgZNQ/2/
The Model:
var myViewModel = function()
{
var self = this;
self.Profiles =ko.observableArray([{
StartDate : '02/01/2012',
EndDate : '01/01/2013',
ProfileID :10,
ProfileName : 'Some Name',
ProjectName : 'Some Project',
ReadingListID : 100,
ReadingListName : 'Some List',
},
{
StartDate : '12/01/2012',
EndDate : '02/27/2013',
ProfileID :12,
ProfileName : 'New Name',
ProjectName : 'New Project',
ReadingListID : 200,
}]);
self.selectedProfileId = ko.observable();
self.getProfile = ko.computed({
read: function() {
for (var i = 0; i < self.Profiles().length; i++) {
if (self.Profiles()[i].ProfileID == self.selectedProfileId()) {
return self.Profiles()[i];
}
}
// in case there was no match, output a blank Profile
return [{
StartDate : '',
EndDate : '',
ProfileID : '',
ProfileName : '',
ProjectName : '',
ReadingListID : '',
ReadingListName : ''
}];
},
write: function(value) {
self.selectedProfileId(value);
},
owner: self
});
}
ko.applyBindings(new myViewModel());
EDIT: Sujesh suggested a much better version of the computedObservable.
self.getProfile = ko.computed(function(){
var profile = ko.utils.arrayFirst(self.Profiles(), function(prof){
return prof.ProfileID == self.selectedProfileId();
});
return profile || {};
});
The HTML:
<table id="readingListApplyToProfile" class="fullWidthTable">
<tr>
<td>
Profile:
</td>
<td>
<select id="cboProfile" name="cboProfile" data-bind="options: Profiles, optionsText: 'ProfileName', 'optionsCaption': 'Select profile...', optionsValue:'ProfileID', value: getProfile "></select>
</td>
</tr>
<tr>
<td>
End Date:
</td>
<td>
<span data-bind="text: getProfile().ProfileName"></span>
</td>
</tr>
</table>
Upvotes: 2
Reputation: 2469
What you are missing is a value binding on the drop down list. Here is a fiddle I created.
http://jsfiddle.net/sujesharukil/sBZvb/1/
<select id="cboProfile" name="cboProfile" data-bind="options: Profiles, optionsText: 'ProfileName', 'optionsCaption': 'Select profile...', optionsValue:'ProfileID', value: selectedProfileId ">
And here is the viewmodel
var myViewModel = function()
{
var self = this;
this.Profiles =ko.observableArray([{
StartDate : '02/01/2012',
EndDate : '01/01/2013',
ProfileID :10,
ProfileName : 'Some Name',
ProjectName : 'Some Project',
ReadingListID : 100,
ReadingListName : 'Some List',
},
{
StartDate : '12/01/2012',
EndDate : '02/27/2013',
ProfileID :12,
ProfileName : 'New Name',
ProjectName : 'New Project',
ReadingListID : 200,
}]);
this.selectedProfileId = ko.observable({}); //this stores the selected id
}
ko.applyBindings(new myViewModel());
Hope that helps.
Suj
Upvotes: 3