Comment puis-je implémenter ngModel sur des éléments personnalisés? (propre zone de liste déroulante)

avec un élément d'entrée simple, je peux faire ceci:

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

cela ne fonctionne pas pour mes éléments personnalisés:

<my-selfmade-combobox [(ngModel)]="name" values="getValues()" required></my-selfmade-combobox>

Comment puis-je l'implémenter?

37
demandé sur maklemenz 2016-02-02 12:30:38

2 réponses

je pense que ce lien répondra à votre question:

nous devons mettre en œuvre deux choses pour y parvenir:

  • Un composant qui fournit la logique de votre composant formulaire. Il n'a pas besoin d'entrée puisque cela sera fourni par ngModel lui-même
  • personnalisé ControlValueAccessor qui permettra de mettre en œuvre le pont entre cette composante et ngModel / ngControl 151990920"

le lien précédent vous donne un échantillon complet...

27
répondu Thierry Templier 2018-03-15 13:47:11

j'ai implémenté le ngModel une seule fois pour l'entrée dans Mes composants partagés et à partir de là je peux l'étendre très simplement.

seulement deux lignes de code:

  1. fournisseurs: [createCustomInputControlValueAccessor (MyInputComponent)]

  2. s'étend dans le composant

mon entrée.composant.ts

import { Component, Input } from '@angular/core';
import { InputComponent, createCustomInputControlValueAccessor } from '../../../shared/components/input.component';
@Component({
   selector: 'my-input',
   templateUrl: './my-input-component.component.html',
   styleUrls: ['./my-input-component.scss'],
   providers: [createCustomInputControlValueAccessor(MyInputComponent)]
})
export class MyInputComponent extends InputComponent {
    @Input() model: string;
}

mon entrée.composant.html

<div class="my-input">
    <input [(ngModel)]="model">
</div>
"151930920 d'entrée".composant.ts

import { Component, forwardRef, ViewChild, ElementRef, OnInit } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
export function createCustomInputControlValueAccessor(extendedInputComponent: any) {
    return {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => extendedInputComponent),
        multi: true
    };
}

@Component({
    template: ''
})
export class InputComponent implements ControlValueAccessor, OnInit {
    @ViewChild('input') inputRef: ElementRef;

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

    // Placeholders for the callbacks which are later provided
    // by the Control Value Accessor
    private onChangeCallback: any;

    // implements ControlValueAccessor interface
    writeValue(value: any) {
        if (value !== this.innerValue) {
            this.innerValue = value;
        }
    }
    // implements ControlValueAccessor interface
    registerOnChange(fn: any) {
        this.onChangeCallback = fn;
    }

    // implements ControlValueAccessor interface - not used, used for touch input
    registerOnTouched() { }

    // change events from the textarea
    private onChange() {
        const input = <HTMLInputElement>this.inputRef.nativeElement;
        // get value from text area
        const newValue = input.value;

        // update the form
        this.onChangeCallback(newValue);
    }
    ngOnInit() {
        const inputElement = <HTMLInputElement>this.inputRef.nativeElement;
        inputElement.onchange = () => this.onChange();
        inputElement.onkeyup = () => this.onChange();
    }
}
0
répondu שלומי אהרוני 2018-07-19 10:56:44