I\'d like to use a property on my ViewModel to toggle which icon to display without creating a separate computed property of the inverse. Is this possible?
I was having the same issue about how to use an opposite of a boolean observable. I have found an easy solution:
var ViewModel = function () {
var self = this;
// When program start, this is set to FALSE
self.isSearchContentValid = ko.observable(false);
self.gatherPlacesData = function () {
// When user click a button, the value become TRUE
self.isSearchContentValid(true);
};
Now on your HTML you should do this
<p data-bind = "visible:isSearchContentValid() === false"> Text 1</p>
<p data-bind = "visible:isSearchContentValid"> Text 2</p>
When the program starts only "Text1" is visible because "false===false is TRUE" and Text2 is not visible.
Lets say we have a button which invokes the gatherPlacesData on click event. Now Text1 won't be visible because "true === false is FALSE" and Text 2 only be visible.
Another possible solution could be using computed observable but, I think is a overcomplicated solution for a so simple problem.
Also can use hidden like this:
<div data-bind="hidden: isString">
<input type="text" class="form-control" data-bind="value: settingValue" />
</div>
I agree with John Papa's comment that there should be a built-in hidden
binding. There are two benefits to a dedicated hidden
binding:
hidden: charted
instead of visible: !charted()
.charted
directly, rather than creating a computed
to observe !charted()
.It's simple enough to create a hidden
binding, though, like this:
ko.bindingHandlers.hidden = {
update: function(element, valueAccessor) {
ko.bindingHandlers.visible.update(element, function() {
return !ko.utils.unwrapObservable(valueAccessor());
});
}
};
You can use it just like the built-in visible
binding:
<i class="icon-search" data-bind="hidden: charted, click: $parent.pie_it"></i>
<i class="icon-remove" data-bind="visible: charted, click: $parent.pie_it"></i>
In order to make the binding aware of changes to the property, I copied the visible binding handler and inverted it:
ko.bindingHandlers.hidden = {
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var isCurrentlyHidden = !(element.style.display == "");
if (value && !isCurrentlyHidden)
element.style.display = "none";
else if ((!value) && isCurrentlyHidden)
element.style.display = "";
}
};
Disclaimer: this solution is for entertainment purposes only.
ko.extenders.not = function (target) {
target.not = ko.computed(function () {
return !target();
});
};
self.foo = ko.observable(true).extend({ not: null });
<div data-bind="text: foo"></div> <!-- true -->
<div data-bind="text: foo.not"></div> <!-- false -->
<!-- unfortunately I can't think of a way to be able to use:
text: foo...not
-->
It's little confusing, as you have to do
visible:!showMe()
so, i did
<span data-bind="visible:showMe">Show</span>
<span data-bind="visible:!showMe()">Hide</span>
<label><input type="checkbox" data-bind="checked:showMe"/>toggle</label>
my model is
var myModel={
showMe:ko.observable(true)
}
ko.applyBindings(myModel);
check in fiddle http://jsfiddle.net/khanSharp/bgdbm/