Reputation: 962
Fiddle here: http://jsfiddle.net/0gmbbv5w/
I've got an object that I pull from the database and bind to a <select>
var NoticeType = function (noticeType) {
this.NoticeTypeId = ko.observable(noticeType.NoticeTypeId);
this.NoticeLevel = ko.observable(noticeType.NoticeLevel);
this.FriendlyName = noticeType.FriendlyNoticeLevel;
}
These will be populated in my viewmodel like so
NoticeType: new NoticeType({
NoticeTypeId: 2,
NoticeLevel: 'info',
FriendlyNoticeLevel: 'Informational'
})
The NoticeTypeId
is being stored in the database, and the NoticeLevel
is a CSS class that is bound to an element. 'FriendlyName` is what shows as the option text.
When adding a new notice, when selecting the type, the NoticeLevel should change the CSS class when the dropdown changes.
<select data-bind="options: $parent.noticeTypes, optionsText: 'FriendlyName', value: noticeType"></select>
<div class="row-fluid">
<div class="span12">
<div class="alert" data-bind="css: alertLevel">
<h4>Just a reminder!</h4>
<span>This is a sample of what your notice will look like. The header is the Subject, and this text is the Message</span>
</div>
</div>
</div>
The only way I can figure out to bind the CSS class when selecting it, is to remove the optionsValue
binding. My problem comes from when selecting an item to edit, the binding doesn't work properly, so the NoticeType
when editing always shows as the "basic" notice type because it can't map the data back.
Is there some way I can accomplish this? Or am I missing something obvious here? When adding a new one, or selecting one to edit and changing the select value, it will update the CSS class properly. When initially selecting one to edit, it does not properly bind the CSS class.
self.editNotice = function (item) {
self.noticeToAdd(new NoticeToAdd(ko.toJS(item)));
}
var NoticeToAdd = function (notice) {
var self = this;
if (!notice) {
notice = {};
}
this.noticeId = ko.observable(notice.NoticeId || notice.noticeId);
this.subject = ko.observable(notice.Subject || notice.subject);
this.body = ko.observable(notice.Body || notice.body);
this.publishDate = ko.observable(notice.PublishDate || notice.publishDate);
this.expireDate = ko.observable(notice.ExpireDate || notice.expireDate);
this.sticky = ko.observable(notice.Sticky || notice.sticky);
this.includeDismiss = ko.observable(notice.IncludeDismissAction || notice.includeDismiss || true);
this.noticeType = ko.observable(notice.NoticeType || notice.noticeType);
this.showDismissal = ko.observable(false);
//CSS binding
this.alertLevel = ko.pureComputed(function() {
return self.noticeType() ? 'alert-' + self.noticeType().NoticeLevel() : 'alert-basic';
});
this.ableToAddNotice = ko.pureComputed(function () {
return $.trim(self.body()) != "";
});
}
Upvotes: 1
Views: 171
Reputation: 4651
The noticeType
used as the value
of the options
binding needs to be one of the objects in the noticeTypes
array. Right now you're telling the <select>
to have the selected item be something not in its list. This is causing the <select>
to default to the first value in the list, the "basic" option.
One solution would be find the object in the noticeTypes
array that "equals" the existing noticeType
and use that as the value
.
Upvotes: 1
Reputation: 1782
Your noticeType objects in test data are not the same objects as in your noticeTypes observable array (instead they are different objects with the same data).
You will need to grab exact objects from noticeTypes array:
//Test data!
var successType = ko.utils.arrayFirst(self.noticeTypes(), function (type) {
return type.NoticeLevel() === 'success';
});
var warningType = ko.utils.arrayFirst(self.noticeTypes(), function (type) {
return type.NoticeLevel() === 'warning';
});
var infoType = ko.utils.arrayFirst(self.noticeTypes(), function (type) {
return type.NoticeLevel() === 'info';
});
var dangerType = ko.utils.arrayFirst(self.noticeTypes(), function (type) {
return type.NoticeLevel() === 'danger';
});
And then you can initialise your test data like this:
self.notices.push(new NoticeToAdd({
NoticeId: 1,
Subject: 'Notice this!',
Body: '<strong>YO!</strong> this is a supre cool notice man',
NoticeType: successType
}));
self.notices.push(new NoticeToAdd({
NoticeId: 2,
Subject: 'Notice this!',
Body: '<strong>YO!</strong> this is a supre cool notice man',
NoticeType: warningType
}));
self.notices.push(new NoticeToAdd({
NoticeId: 3,
Subject: 'Notice this!',
Body: '<strong>YO!</strong> this is a supre cool notice man',
NoticeType: infoType
}));
self.notices.push(new NoticeToAdd({
NoticeId: 4,
Subject: 'Notice this!',
Body: '<strong>YO!</strong> this is a supre cool notice man',
NoticeType: dangerType
}));
self.notices.push(new NoticeToAdd({
NoticeId: 5,
Subject: 'Notice this!',
Body: '<strong>YO!</strong> this is a supre cool notice man'
}));
See updated fiddle:
Obviously with proper data coming from the server this should be much simpler:
var someType = ko.utils.arrayFirst(self.noticeTypes(), function (type) {
return type.NoticeTypeId() === NoticeTypeIdFromTheServer;
});
Upvotes: 1