Reputation: 9146
What I'm attempting to do is create a dropdown containing a list of projects. This dropdown houses 2 categories of projects: favorite and non-favorite (designated by a 1 or 0), the favorite projects being in an opt-group.
<select data-bind="foreach: $root.favorites, value: project_id, event: {change: console.log('changed') }" class="selectpicker" data-live-search="true">
<!-- ko if: $data == 1 -->
<optgroup data-bind="attr: {label: 'Favorites'}, foreach: $root.projects">
<!-- ko if: favorite() == "1" -->
<option data-bind="text: project_name, value: project_id"></option>
<!-- /ko -->
</optgroup>
<!-- /ko -->
<!-- ko if: $data == 0 -->
<option data-divider="true"></option>
<!-- ko foreach: $root.projects -->
<!-- ko if: favorite() == 0 -->
<option data-bind="text: project_name, value: project_id"></option>
<!-- /ko -->
<!-- /ko -->
<!-- /ko -->
</select>
When a 'favorited' project is selected, the button to the left of the select should have a class of favorited
, and the class should be removed if a project that is not a favorite is selected.
<button class="btn btn-default btn-sm" data-bind="click: , css: { favorited: true }" style="padding: 0px 7px; font-size: 20px; margin-left: 10px; color: #cccccc;"><span class="glyphicon glyphicon-star" style="padding-top: 5px;"></span></button>
(the code currently just sets favorited on the button by default, just to show what it should look like)
When the button to the left of the select is clicked, it should also toggle the favorite
property of the selected project -- 1 if it's now a favorite, and a 0 if it is no longer a favorite.
So, my questions are:
favorite
status of the selected project?favorite
status of the selected project when the button is clicked?I also have full control of the data coming in, so that can be modified if needed to make a cleaner/simpler solution.
Thanks in advance.
Upvotes: 0
Views: 484
Reputation: 3118
See my implementation.
Edit: modifed fiddle based on comments
To reduce a couple of the == 0
, == 1
checks. Turn the favorite property/attribute into a boolean. Since the css is driven by favorite
of a project, let the value of the <select>
be an actual project object. Using knockout aliasing it looks like
foreach: {data: $root.projects, as: 'projectAlias'}"
now we can properly use the selectedProject
variable in your model. Make sure to remove the undefined
initializer and set it to an observable: self.selectedProject = ko.observable();
Now the css binding can "listen" to changes on your selection. You can achieve this several different ways. I chose to use a computed
.
self.cssToggle = ko.computed(function() {
if(self.selectedProject()){
return self.selectedProject().favorite();
}
return false;
});
Bind it css: { favorited: cssToggle}
.
To enable/implement the click functionality of the favorite button, bind a method click: toggleFavorite
and provide it in the viewmodel:
self.toggleFavorite = function () {
var currentState = self.selectedProject().favorite();
self.selectedProject().favorite(!currentState);
}
At this point, you should have the behavior you desire. I think I covered everything I changed, reference the fiddle in case I missed something. It may be possible to reduce the foreach
bindings to a single pass of projects
. I may revisit that as I "fiddled" with this while waiting on something else.
Upvotes: 2