web-dev-qa-db-fra.com

Liaison de données bidirectionnelle Angular2

Je sais que Angular2 n'a pas de liaison de données bidirectionnelle, mais existe-t-il un moyen d'imiter le comportement de liaison de données bidirectionnelle d'Angular1.x?

21

Remarque - faites défiler la réponse pour la liaison ng-model

Vous pouvez en fait le faire, juste que vous devez invoquer un tick interne de changelistener (similaire à digest) pour mettre à jour la liaison dans la zone, vous pouvez simplement ajouter un (keyup) événement pour cela. De même, vous pouvez également utiliser des liaisons de directive avec properties dictionnaire de paramètres de composant.

Exemple:-

<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-->

Afficher comme:

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

Le composant parent a une zone de texte et une étiquette.

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);
  }

}

Maintenant, l'afficher également dans le composant enfant:

@Component({
  selector: 'edit',
  template: `<p><b>Child Component:</b></p>{{text.value}}`
})

export class Edit {
    @Input() text:any;
}

Démo



Mise à jour - modèle ng pour la liaison bidirectionnelle

Bien que Angular2 soit lié une seule fois par défaut, ngModel sugar a été introduit pour obtenir une liaison bidirectionnelle. Avec cela, vous pouvez par exemple:

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

Voici l'utilisation des crochets ([..]) suggère la liaison de propriété et les crochets ((..)) pour la liaison d'événement. Fondamentalement, lorsque vous utilisez ng-model, vous activez les deux liaisons ngModel est plutôt un événement. Dans les coulisses, il crée un événement observable (avec EventEmitter) pour suivre les changements value dans l'élément lié et mettre à jour la propriété liée respectivement. Par exemple:-

Inclure le formulaire

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

et avec forme

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

sans forme

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

plus nécessaire inclure la dépendance formDirectives dans l'annotation de vue.

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

Démo

Lisez également le Belle écriture de Victor Savkin sur la liaison bidirectionnelle dans angular2 en créant l'événement ng-model et comment il fonctionne.

19
PSL

Vous pouvez maintenant simplement le faire en utilisant ngModel en utilisant la syntaxe suivante:

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

La combinaison des crochets carrés et ronds signifie "liaison bidirectionnelle".

S'il vous plaît voir le plunk ici

15
JDTLH9

Oui, il y a une liaison bidirectionnelle dans angular2. Voir ici: https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngModel

Alors, comment l'utiliser dans des composants personnalisés?

Ce que j'aime faire, c'est quelque chose comme ceci:

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; 
}

Et utilisez-le comme

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

Vous pouvez également émettre la nouvelle valeur là où elle est réellement modifiée. Mais je trouve cela très pratique de faire cette gloabaly dans une méthode setter et je n'ai pas à me soucier par exemple quand je le lie directement à ma vue.

11
Mario Eis

Vous pouvez le faire en attachant aux événements sur le champ de saisie et en mettant à jour la valeur interne comme cela se fait dans cet exemple:

http://plnkr.co/edit/lOFzuWtUMq1hCnrm9tGA?p=preview

Créez un composant possédant un attribut interne contenant le label this.label et un rappel changeLabel qui attend un objet événement

@Component({
  selector: 'app',
  templateUrl: 'bound.html'
})
class App {
  label: string;
  constructor() {
    this.label = 'default label'
  }
  changeLabel(event) {
    this.label = event.target.value;
  }
}

bootstrap(App);

Créez votre modèle et attachez le rappel à l'événement approprié (vous pouvez l'attacher à l'événement keypress mais vous pourriez avoir besoin d'un délai d'attente. Je l'ai attaché à l'événement change pour plus de simplicité (ce qui signifie que vous devrez peut-être taper l'entrée pour voir la mise à jour).

<label for="myinput">{{label}}</label>
<input id="myinput" type="text"/>
<p></p>You can change the label above by typing something below</p>
<label for="labeltext">New Label Text</label>
<input type="text" id="labeltext" (change)="changeLabel($event)"/>
6
unobf

Il existe une autre façon de tromper Angular2 en liaison bidirectionnelle. Ne passez pas une propriété mais un objet dans le composant. Si vous passez un objet via une liaison à sens unique, toutes ses propriétés sont en fait à double sens. Cela rend le composant moins polyvalent car il a besoin de connaître l'objet, mais dans de nombreux cas, il est toujours utile.

J'ai un composant qui ressemble à ceci:

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;
    }
}

Il est invoqué comme ceci:

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

L'objet vidéo lui-même est lié à sens unique, mais toutes ses propriétés peuvent être utilisées pour la liaison bidirectionnelle.

5
hholtij

Voici un plongeur simple qui démontre les approches unidirectionnelles, bidirectionnelles et événementielles en action selon Angular2 2.0.0-beta.17

http://plnkr.co/eXZMo

Événement bidirectionnel et propriété

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

Propriété à sens unique

<input [value]="name" />

Événementiel

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

Nous pouvons creuser Angular docs for more

2
Davut Gürbüz

Depuis les documents:

Liaison bidirectionnelle ([(...)])

Vous souhaitez souvent afficher à la fois une propriété de données et la mettre à jour lorsque l'utilisateur apporte des modifications.

Du côté de l'élément, il faut combiner la définition d'une propriété d'élément spécifique et l'écoute d'un événement de changement d'élément.

Angular propose à cet effet une syntaxe de liaison de données bidirectionnelle spéciale, [(x)]. La syntaxe [(x)] combine les crochets de la liaison de propriété, [x], avec les parenthèses de la liaison d'événement, (x).

[( )] = BANANA IN A BOX

Visualisez une banane dans une boîte pour vous souvenir que les parenthèses vont à l'intérieur des crochets.

Pour plus d'informations, voir

1
georgeawg

C'est simple, essayez ceci;

<input [(ngModel)]="property" placeholder="property Value"/>
<h1>{{property}}</h1>
0
Jalasem