Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting two way binding on $data inside a template

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

like image 714
Brian Pritchard Avatar asked Jan 24 '12 15:01

Brian Pritchard


People also ask

How do you get data flowing both ways between component properties and template events?

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.

How do you do two way data binding?

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.

What is the correct way for performing two way binding in Angular?

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.

Is ngModel two way binding?

Two-way binding of HTML Form components is achieved using the ngModel directive in the Angular framework.


1 Answers

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

like image 123
RP Niemeyer Avatar answered Oct 28 '22 03:10

RP Niemeyer