I am still fairly new to knockout and I am trying to display and hide bootstrap tabs using knockout.
basically I have a puted observable:
self.isActive = koputed(function () {
var selected = ko.utils.arrayFirst(self.padParticipant(), function (item) {
return item.ParticipationStatus == 'Active';
});
return selected !== null ? true : false;
});
to update these tabs:
<ul class="nav nav-tabs" id="padTabs">
<li data-bind="fadeVisible: !isActive()"><a href="#joinPad">Join PAD</a></li>
<li class="active"><a href="#history">History</a></li>
<li data-bind="fadeVisible: isActive()"><a href="#update">Update Subscription</a></li>
</ul>
The puted is working correctly in the sense that when I refresh the page the correct tabs are hidden, but I need it to work without refreshing.
I am still fairly new to knockout and I am trying to display and hide bootstrap tabs using knockout.
basically I have a puted observable:
self.isActive = ko.puted(function () {
var selected = ko.utils.arrayFirst(self.padParticipant(), function (item) {
return item.ParticipationStatus == 'Active';
});
return selected !== null ? true : false;
});
to update these tabs:
<ul class="nav nav-tabs" id="padTabs">
<li data-bind="fadeVisible: !isActive()"><a href="#joinPad">Join PAD</a></li>
<li class="active"><a href="#history">History</a></li>
<li data-bind="fadeVisible: isActive()"><a href="#update">Update Subscription</a></li>
</ul>
The puted is working correctly in the sense that when I refresh the page the correct tabs are hidden, but I need it to work without refreshing.
Share edited Mar 26, 2013 at 22:27 metalwings 1733 silver badges14 bronze badges asked Mar 26, 2013 at 22:22 ThreadedLemonThreadedLemon 4891 gold badge10 silver badges25 bronze badges 5-
so padParticipant is an observable array? is the whole thing set in a $(document).ready() {}? Also, is the ternary necessary? Could you just say
return selected !== null;
? – dmoss18 Commented Mar 26, 2013 at 22:28 - This is odd, is that html autogenerated by something? Why is the binding different, and missing from the middle one? Can you try to replicate the behavior in a fiddle? – Kyeotic Commented Mar 26, 2013 at 22:31
- padParticipant is an observable array. Yes, the whole thing is set in a $(document).ready(function () {}. – ThreadedLemon Commented Mar 26, 2013 at 22:32
- The binding is only on the first two because the middle tab is always visible. If the first tab is visible the third one should not be and vice versa – ThreadedLemon Commented Mar 26, 2013 at 22:54
-
@Slade You say it only behaves correctly when you refresh, that implies that some type of state change that is suppose to trigger an update to the UI is not. Are you expecting the tab visibility to change when the
ParticipationStatus
of the objects in your observable array change??? – Matthew Cox Commented Mar 27, 2013 at 2:18
1 Answer
Reset to default 9The issue has to do with understanding what is happening in the Knockout framework when you use puted observables in addition to the rules of observable arrays. First let's look at a note about observable arrays:
Key point: An observableArray tracks which objects are in the array not the state of those objects
Simply putting an object into an observableArray doesn’t make all of that object’s properties themselves observable. Of course, you can make those properties observable if you wish, but that’s an independent choice. An observableArray just tracks which objects it holds, and notifies listeners when objects are added or removed.
This is the same cautionary mistake you are making in this line of code, since this isn't an observable, rather just a property of an object in the array,:
return item.ParticipationStatus == 'Active';
Furthermore, we need to understand how a puted observable operates:
Whenever you declare a puted observable, KO immediately invokes its evaluator function to get its initial value.
While your evaluator function is running, KO keeps a log of any observables (or puted observables) that your evaluator reads the value of.
When your evaluator is finished, KO sets up subscriptions to each of the observables (or puted observables) that you’ve touched. The subscription callback is set to cause your evaluator to run again, looping the whole process back to step 1 (disposing of any old subscriptions that no longer apply).
KO notifies any subscribers about the new value of your puted observable.
So when you made your puted observable, the only subscription that was created to watch for changes was one to the observable array self.padParticipant()
.
Since the UI change of state is dependent upon the ParticipationStatus
changing, this means this property needs to be an observable element within each object in the array, otherwise when it's state changes, there will be no way for the puted to be aware of that change and update the UI.