Angular2 liaison de données bidirectionnelle

Je sais Qu'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
demandé sur Ronald Wildenberg 2015-05-26 23:28:39

7 réponses

Remarque - faites défiler vers le bas la réponse pour le gn-liaison du modèle

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

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

}

L'affiche maintenant 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 - ng-model pour 2 voies de liaison

Bien Qu'Angular2 soit lié une fois par défaut, ngModel sugar a été introduit pour obtenir une liaison à 2 voies. Avec cela, vous pourriez faire par exemple:

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

Ici, l'utilisation de crochets ([..]) suggère la liaison de propriétés et les crochets ronds ((..)) pour la liaison d'événements. Fondamentalement quand vous utilisez ng-model, vous activez les deux liaisons ngModel est plus 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 formDirectives:

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

Et avec la 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 en vue annotation.

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

Démo

Lisez aussi la belle écriture de Victor Savkin sur la liaison bidirectionnelle dans angular2 en créant l'événement ng-model et son fonctionnement.

19
répondu PSL 2016-06-13 03:54:38

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

Veuillez voir le plunk ici

14
répondu JDTLH9 2016-10-03 13:08:50

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 les composants personnalisés?

Ce que j'aime faire est quelque chose 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 l'utiliser comme

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

Vous pouvez également émettre la nouvelle valeur où elle est réellement modifiée. Mais je trouve très pratique de faire cela gloabaly dans une méthode setter et ne pas avoir à déranger par exemple quand je le lie directement à mon vue.

9
répondu Mario Eis 2016-10-09 12:09:53

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

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

Créer un composant qui a un attribut interne qui contient l'étiquette this.label et un rappel changeLabel qui attend un objet d'é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 timeouts. Je l'ai attaché à l'événement change pour plus de simplicité (ce qui signifie que vous devrez peut-être supprimer 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
répondu unobf 2016-05-25 15:44:53

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 unidirectionnelle, toutes ses propriétés sont en fait liées dans les deux sens. Il rend le composant moins polyvalent que les besoins 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 film lui-même est lié à un sens mais tous ses les propriétés peuvent être utilisées pour la liaison bidirectionnelle.

5
répondu hholtij 2016-06-13 01:35:47

Voici un simple plunker qui démontre des approches à Sens Unique, bidirectionnelles et événementielles en action selon Angular2 2.0.0-beta.17

Http://plnkr.co/eXZMoU

Événement bidirectionnel et propriété

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

Propriété à Sens Unique

<input [value]="name" />

Événement piloté

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

Nous pouvons creuser des documents angulaires pour plus

1
répondu Davut Gürbüz 2016-11-09 14:59:09

C'est simple, essayez ceci;

<input [(ngModel)]="property" placeholder="property Value"/>
<h1>{{property}}</h1>
0
répondu Jalasem 2016-06-17 18:10:12