Reputation: 587
I am using the same observable for display and edit views as follows. I would like a default text ('-') to appear in the display view whenever the return value is null
, but I do not want that in the edit view. How could that be achieved?
function ViewModel() {
var self = this;
self.txt1 = ko.observable();
self.txt2 = ko.observable();
}
// View Mode
<span data-bind="text:txt1"></span>
<span data-bind="text:txt2"></span>
// Edit Mode
<input type="text" data-bind="value:txt1" />
<input type="text" data-bind="value:txt2" />
Upvotes: 0
Views: 3485
Reputation: 4971
This might not be the most paradigmatic Knockout.js solution but it's working well and it's very quick.
Instead of the <span>
you could use an HTML <input />
, with placeholder="-" readonly="readonly"
. You may want also to style it so that you hide borders.
<input class="readonly" data-bind="value:txt1" readonly placeholder="-" />
<input class="readonly" data-bind="value:txt2" readonly placeholder="-" />
.readonly {
border: 0;
}
Upvotes: 1
Reputation: 32202
An alternative approach to computed
s as per my other answer is to write an entire new custom binding handler. This means you only have the one observable on your view model, with the logic contained within the binding handler instead. Note that you need to change the view to use this binding handler, rather than the text
binding it was using:
ko.bindingHandlers.textdefault = {
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var v = valueAccessor();
var d = allBindings.get('defaultIfBlank') || '-';
element.innerText = (v() == null || v() == '') ? d : v();
}
};
function ViewModel() {
var self = this;
self.txt1 = ko.observable();
self.txt2 = ko.observable();
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
// View Mode<br />
<span data-bind="textdefault:txt1"></span><br />
<span data-bind="textdefault:txt2, defaultIfBlank: '$'"></span><br />
<br />
// Edit Mode<br />
<input type="text" data-bind="value:txt1" /><br />
<input type="text" data-bind="value:txt2" /><br />
Note that in this approach, we can also customise the handler through the allBindings
variable - in the above I have added a parameter to allow customising of which character is displayed if the entry is blank.
Upvotes: 0
Reputation: 32202
You can use a computed
observable to return a value for the view mode, using it to check the value currently stored and return -
if necessary:
function ViewModel() {
var self = this;
self.txt1 = ko.observable();
self.txt2 = ko.observable();
self.viewtxt1 = ko.computed(function() {
if (self.txt1() == null)
return '-';
return self.txt1();
});
self.viewtxt2 = ko.computed(function() {
//txt2 is checked for null or blank, use whichever is appropriate
if (self.txt2() == null || self.txt2() == '')
return '-';
return self.txt2();
});
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
// View Mode<br />
<span data-bind="text:viewtxt1"></span><br />
<span data-bind="text:viewtxt2"></span><br />
<br />
// Edit Mode<br />
<input type="text" data-bind="value:txt1" /><br />
<input type="text" data-bind="value:txt2" /><br />
In the above there are two different checks. txt1
is checked just for null
, and so if you edit it and delete all characters, the blank value will persist in the view. txt2
is checked for both null
and blank, so removing all characters will reset the view back to -
. Use whichever one is appropriate to you.
Upvotes: 1