I am trying to setup generic Knockout templates that can be toggled between edit and readonly mode based on data type. If you've ever used ASP.NET's dynamic data: it's like their field templates. For example:
<script type="text/html" id="text">
<!-- ko if: $root.editable -->
<input type="text" data-bind="value: $data" />
<!-- /ko -->
<!-- ko ifnot: $root.editable -->
<span data-bind="text: $data"></span>
<!-- /ko -->
</script>
This is used like this:
<label><input type="checkbox" data-bind="checked: editable" /> Editable</label>
<p>Name: <input data-bind="value: name" /></p>
<p>Name2: <span data-bind="template: { name: 'text', data: name }"></span></p>
With the following view model:
var viewModel = {
name: ko.observable("Brian"),
editable: ko.observable(true)
};
The idea is to be able to use templates at the field level like in the "Name2" example, instead of explicit elements/controls. This allows entire forms to be easily toggled between edit and read mode without having large sections of mostly duplicated markup. This also allows reuse of common data type editing/display markup, for example using datepickers for date fields, etc.
The Problem
The $data
pseudo variable inside the template does not have two way binding. It will reflect the current value in the observable, but changes in the input control will not set the value.
How can I get two way binding on $data
?
See also this jsfiddle
Two-way data binding: Data flows both ways. For example: <input type="text" [(ngModel)]="foobar"> (The foobar variable needs to be defined in the component). The input element and foobar will have the same value and when one changes, the other one changes to the same value accordingly.
For two-way data binding, declare a private property and access its value using get and set methods in the component class. Then, assign that property to [(ngModel)] . For example, declare a private property with a get and set method, as shown below. Now, assign userName to [(ngModel)] in the template.
Angular's two-way binding syntax is a combination of square brackets and parentheses, [()] . The [()] syntax combines the brackets of property binding, [] , with the parentheses of event binding, () , as follows.
Two-way binding of HTML Form components is achieved using the ngModel directive in the Angular framework.
The simplest choice is to pass an object to the template binding that allows you to access the actual observable like:
template: { name: 'text', data: {field: name} }
Then, bind against "field" instead of "$data" in your template.
Another thing to consider would be using a function to determine your template, then you can use separate templates for edit/view like:
http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html
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