I have a form with a lot of inputs.
I am using the following syntax within my form: <!-- ko if: PropertyName -->
. I am using this statement in the form for specific fields. This allows me to hide values that are not defined (actually not hide, but remove from DOM).
However, I do not need to hide them on the fly. I mean, when value was not empty and was loaded, then user can edit it, and user can empty it. In this case input disappears, I do not need this.
Can you suggest me – how to change my markup and what binding to use?
<!-- ko if: IsEmptyOnLoad(Property1) -->.
<input type="text" data-bind="value: Property1" />
<!-- /ko -->
<!-- ko if: IsEmptyOnLoad (Property2) -->.
<input type="text" data-bind="value: Property2" />
<!-- /ko -->
var myModel = function() {
var self = this;
self.Property1= ko.observable("non-empty");
self.Property2= ko.observable();
//self.IsEmptyOnLoad is not implemented, how to implement?
};
var m = new myModel();
ko.applyBindings(m);
You can try playing with the corresponding JSFiddle.
It could be strange, but I really have business scenario:
Just create custom binding with empty update
method. You can do whatever you want at binding init
on page load (at knockout binding apply to be more specific).
ko.bindingHandlers.ifOnce = {
init: function(element, valueAccessor) {
var observable = valueAccessor(); // get observable
var value = observable(); // get value of observable
var isEmpty = !value; // do whatever check you want
// and remove element from dom if empty
if (isEmpty) {
element.parentNode.removeChild(element);
}
},
update: function(element, valueAccessor) {
// do nothing on update
}
};
Working example: http://jsfiddle.net/2FTEM/6/
Lets go one step further. You asked how to create IsEmptyOnLoad
. You can do this by using Knockout virtual elements and some useful methods they have. I.e.: ko.virtualElements.emptyNode
will remove everything between Knockout <!-- ko -->
tags http://knockoutjs.com/documentation/custom-bindings-for-virtual-elements.html
ko.bindingHandlers.IsEmptyOnLoad = {
init: function(element, valueAccessor) {
var observable = valueAccessor(); // get observable
var value = observable(); // get value of observable
var isEmpty = !value; // do whatever check you want
// and remove element from dom if empty
if (isEmpty) {
ko.virtualElements.emptyNode(element);
}
},
update: function(element, valueAccessor) {
// do nothing on update
}
};
ko.virtualElements.allowedBindings.IsEmptyOnLoad = true;
Working example: http://jsfiddle.net/2FTEM/7/
An interesting problem that has so far generated some inventive answers. It's a common trend that people seem to have a phobia of putting logic into the view-model. As the name suggests, it should be designed as an interface between the view and the model. Firstly, I would re-factor the view-model, something like this;
var myModel = function() {
var self = this;
var property = function (content, availibility) {
return {
content: ko.observable(content),
availibility: availibility
};
}
self.Property1 = property('non-empty', true);
self.Property2 = property();
};
Now your HTML can be simple;
<input type="text" data-bind="visible: Property1.availibility, value: Property1.content" />
<input type="text" data-bind="visible: Property2.availibility, value: Property2.content" />
I've also provided a fork of the JSFiddle for your reference
UPDATE: Re-factored for simplicity and minimal repetition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With