Angular2 two-way data binding

前端 未结 8 1808
谎友^
谎友^ 2020-12-15 05:10

I know Angular2 doesn\'t have two-way data binding but is there a way to mimick the two-way data binding behavior from Angular1.x?

相关标签:
8条回答
  • 2020-12-15 05:27

    There is another way to trick Angular2 into two-way binding. Don't pass a property but an object into the component. If you pass an object via one-way binding all of its properties are in fact two-way bound. It makes the component less versatile as it needs to know the object but in many cases it's still useful.

    I have a component that looks like this:

    import { Component, Input }    from "@angular/core";
    import { NgSwitch, NgSwitchWhen, NgSwitchDefault }    from "@angular/common";
    
    export class Movie
    {
        public Title: string;
        public Rating: number;
        public Seen: boolean;
    }
    
    @Component
    ({
        selector: "hh-image-checkbox",
        template: `
            <div [ngSwitch]="movie.Seen"> 
                <div *ngSwitchWhen="true">
                    <img src="/Content/res/CheckTrue.png" (click)="onClick()"> 
                </div> 
                <div *ngSwitchDefault> 
                    <img src="/Content/res/CheckFalse.png" (click)="onClick()"> 
                </div> 
            </div>
            `,
        directives: [NgSwitch, NgSwitchWhen, NgSwitchDefault]
    })
    
    export class ImageCheckboxComponent
    {
        @Input() movie: Movie;
    
        public onClick()
        {
            this.movie.Seen = !this.movie.Seen;
        }
    }
    

    It is invoked like this:

    <hh-image-checkbox [movie]="movie"></hh-image-checkbox>
    

    The movie object itself is one-way bound but all of its properties can be used for two-way binding.

    0 讨论(0)
  • 2020-12-15 05:29

    Its simple, try this;

    <input [(ngModel)]="property" placeholder="property Value"/>
    <h1>{{property}}</h1>
    
    0 讨论(0)
  • 2020-12-15 05:33

    You can now simply do this by using ngModel using the following syntax:

    <input [(ngModel)]="myProp" />
    

    The combination of the square and round brackets means "two-way binding".

    Please see the plunk here

    0 讨论(0)
  • 2020-12-15 05:35

    Note - scroll down the answer for ng-model binding

    You could actually do that, just that you need to invoke internal changelistener tick (similar to digest) to update binding in the zone, You can just add a (keyup) event for that. Similarly you could use directive bindings as well with properties dictionary of component settings.

    Example:-

    <input #label (keyup)> 
    <!-- variable #label represented as the element itself and accessible as property on controller instance 
     You can even bind keyup to a function or another another function and pass value from the label property-->
    

    Display as:

    <p>{{label.value}}</P>
    

    Parent Component has a textbox and a label.

    import { Component, bootstrap} from '@angular/core';
    import {Display} from 'display';
    
    @Component({
      selector: 'my-app',
      template: `<p><b>Parent Component:</b><p><input #label (keyup) (change)="handleChange(label.value)">
            <p>{{label.value}}</P> <display [text]="label"></display></p></p>`,
      directives: [Display]
    })
    
    class MainComponent {
      label: any;
    
      constructor() {
    
      }
    
      handleChange(label){
        this.label = label;
        console.log(this.label);
      }
    
    }
    

    Now displaying it in child component as well:

    @Component({
      selector: 'edit',
      template: `<p><b>Child Component:</b></p>{{text.value}}`
    })
    
    export class Edit {
        @Input() text:any;
    }
    

    Demo



    Update - ng-model for 2-way binding

    Though Angular2 is one-time bound by default, ngModel sugar has been introduced to achieve 2-way binding. With that you could do for instance:

    <input ngControl="name" [(ngModel)]="name">
    

    Here usage of square brackets ([..]) suggests the property binding and round brackets ((..)) for event binding. Basically when you use ng-model, you are enabling both the bindings ngModel is more of an event. Behind the scenes it creates an observable event(with EventEmitter) to track the value changes in the bound element and update the bound property respectively. For example:-

    Include formDirectives:

     import {FORM_DIRECTIVES} from '@angular/common';
    

    and with form

       <form (ngSubmit)="onSubmit()" let-f="form">
          <input ngControl="name" [(ngModel)]="name">
          <button>Click me and check console</button>
       </form>
    

    without form

      <input  [(ngModel)]="name">
      <button (click)="onSubmit()">Click me and check console</button>
    

    not necessary anymore include formDirectives dependency in view annotation.

    @Component({
      template: .....,
      directives: [FORM_DIRECTIVES]
    })
    

    Demo

    Also read the nice write up from Victor Savkin on Two-way binding in angular2 by creating the ng-model event and how it works.

    0 讨论(0)
  • 2020-12-15 05:36

    Here is a simple plunker which demonstrates one way, two way and event driven approaches in action according to Angular2 2.0.0-beta.17

    http://plnkr.co/eXZMoU

    Two-way Event and property

    <input [(ngModel)]="name" />
    

    One way property

    <input [value]="name" />
    

    Event driven

    <input (input)="name=$event.target.value">
    

    We can dig Angular docs for more

    [UPDATE 1/26/2020]

    Since Angular2 beta libs are removed from project CDN ! above plnkr link doesn't work anymore.

    Use below new plnkr Angular 6+ page , I ported previous page to NPMJS, new angular edition and new plnkr!

    http://next.plnkr.co/edit/4okdOSgw3SMvdktR?preview

    0 讨论(0)
  • 2020-12-15 05:37

    Yes there is two-way binding in angular2. See here: https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngModel

    So, how to use it in custom components?

    What I like to do is something this:

    private currentSelectedItem: MachineItem;
    @Output() selectedItemChange: EventEmitter<MachineItem> = new EventEmitter<MachineItem>();
    
    @Input() set selectedItem(machineItem: MachineItem) {
        this.currentSelectedItem = machineItem;
        this.selectedItemChange.emit(machineItem); 
    }
    
    get selectedItem(): MachineItem {
        return this.currentSelectedItem; 
    }
    

    And use it like

    <admin-item-list [(selectedItem)]="selectedItem"></admin-item-list>
    

    You can also emit the new value where it is actually changed. But I find it quite convenient to do that gloabaly in a setter method and don't have to bother e.g. when I bind it directly to my view.

    0 讨论(0)
提交回复
热议问题