2017-02-16 3 views
1

Ces liaisons fonctionnent très bien:liaisons Déléguer du composant angulaire 2 à l'élément imbriqué

<input type="checkbox" (click)="foo.bar()" [(ngModel)]="foo.baz"> 

Mais comment puis-je déléguer ces liaisons à l'intérieur d'une entrée un composant?

<custom-checkbox>Check me!</custom-checkbox> 

... et voici la « coutume-checkbox.component.html »:

<span class="checkbox-wrap"> 
    <input type="checkbox" class="checkbox"> <!-- This should have all the bindings --> 
    <span class="checkbox-styling"></span> 
    <span class="checkbox-label"><ng-content></ng-content></span> 
</span> 

J'utilise angulaire 1 pendant quelques années, mais juste commencé à utiliser angulaire 2 cette semaine . J'ai lu beaucoup d'articles tels que Custom form controls in Angular, docs angulaires, d'autres questions Stack Overflow quelque peu semblables, et le TypeScript utilisé sur Material Checkbox d'Angular 2 mais je ne comprends toujours pas comment ils ont tiré ceci. Il semble que cela devrait être plus simple.

Ceci est l'un des nombreux éléments d'interface utilisateur personnalisés que j'ai besoin de faire, donc j'espère que cet exemple va m'aider à comprendre les principes et la mise en œuvre qui me manque.

Je sais que je pourrais utiliser une case à cocher d'entrée avec un sélecteur dessus, et l'envelopper, mais je veux être aussi propre que le Angular 2 Material checkbox est. Je fais essentiellement la même chose (matériau angulaire 2), mais avec notre propre style, et beaucoup plus simpliste que toutes les options qu'ils offrent. Tout comme ils ont dit,

< md-case> fournit les mêmes fonctionnalités que un type d'entrée < native = "checkbox"> amélioré avec matériel style design et animations.

et c'est ce que j'essaie de faire.

+0

mettre des liaisons directement sur le composant –

+0

@RomanC Si je fais cela, le modèle ne s'appliquera pas à l'état de vérité de la case, et j'obtiens aussi cette erreur dans la console: 'EXCEPTION: Erreur dans./ AppComponent class AppComponent - modèle en ligne: 4: 41 provoqué par: Aucun accesseur de valeur pour le contrôle de formulaire avec un attribut de nom non spécifié ' –

Répondre

0

Bien que la fonction de lien de angulaire 1 semblait rendre ce processus plus facile, cet article semble me donner le courage que Matériel angulaire 2 est utilise par le biais d'interfaces intégrées avec un bon exemple: Angular 2: Connect your custom control to ngModel with Control Value Accessor.

Cela permet le développement Les équipes utilisent mes composants en se liant directement à un composant mais en relayant les liaisons à la case à cocher (ou à tout autre élément de formulaire) dans mon modèle.

Je cite le site pour la facilité et la persistance de la documentation en cas de rupture de lien:

Alors sans plus tarder, voici notre composant:

import { Component, forwardRef } from '@angular/core'; 
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; 

const noop =() => { 
}; 

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = { 
    provide: NG_VALUE_ACCESSOR, 
    useExisting: forwardRef(() => CustomInputComponent), 
    multi: true 
}; 

@Component({ 
    selector: 'custom-input', 
    template: `<div class="form-group"> 
        <label><ng-content></ng-content> 
         <input [(ngModel)]="value" 
           class="form-control" 
           (blur)="onBlur()" > 
        </label> 
       </div>`, 
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] 
}) 
export class CustomInputComponent implements ControlValueAccessor { 

    //The internal data model 
    private innerValue: any = ''; 

    //Placeholders for the callbacks which are later providesd 
    //by the Control Value Accessor 
    private onTouchedCallback:() => void = noop; 
    private onChangeCallback: (_: any) => void = noop; 

    //get accessor 
    get value(): any { 
     return this.innerValue; 
    }; 

    //set accessor including call the onchange callback 
    set value(v: any) { 
     if (v !== this.innerValue) { 
      this.innerValue = v; 
      this.onChangeCallback(v); 
     } 
    } 

    //Set touched on blur 
    onBlur() { 
     this.onTouchedCallback(); 
    } 

    //From ControlValueAccessor interface 
    writeValue(value: any) { 
     if (value !== this.innerValue) { 
      this.innerValue = value; 
     } 
    } 

    //From ControlValueAccessor interface 
    registerOnChange(fn: any) { 
     this.onChangeCallback = fn; 
    } 

    //From ControlValueAccessor interface 
    registerOnTouched(fn: any) { 
     this.onTouchedCallback = fn; 
    } 

}

Nous sommes alors pouvoir utiliser ce contrôle personnalisé comme suit:

<form> 

    <custom-input name="someValue" 
        [(ngModel)]="dataModel"> 
      Enter data: 
    </custom-input> 

</form>

Merci Almero Steyn !!

+0

Serait-il possible d'utiliser un formControl au lieu de ngModel? Je demande comme vous pouvez utiliser formControl.valueChanges en tant qu'abonnement et déclencher onChangeCallback. – Gambo

+1

@Gambo Malheureusement, je dois supporter ngModels sur tout. Mais merci de regarder une alternative. –