Пользовательский ввод формы не привязан к модели

Я пытаюсь ввести пользовательскую форму в Angular 4. Это простой пример, но я не могу заставить компонент привязаться к ngModel. Я могу передать этому компоненту значение по умолчанию из родительского контроллера, но когда я изменяю значение на этом входе, пользовательский интерфейс регистрирует изменение, но модель в контроллере не показывает новое значение.

Вот мой нестандартный компонент:

import { Component, Input, forwardRef, Output, EventEmitter, ElementRef, Renderer } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl } from '@angular/forms';

@Component({
    selector: 'input-test2',
    template:
        `
           <input type="text" class="form-control" placeholder="Symbol"  [(ngModel)]="value" [maxlength]="5" >     
        `,
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => InputTestComponent),
            multi: true
        },
    ]
})
export class InputTestComponent implements ControlValueAccessor {
    @Input('value') value = false;
    
    private propagateChange = (_: any) => { };
    private propagateTouch = (_: any) => { };
    
    writeValue(value: any): void {
        if (value) {
            this.value = value;
        }
    }
    
    registerOnChange(fn: (_: any) => void): void {
        this.propagateChange = fn;
    }
    registerOnTouched(fn: () => void): void {
        this.propagateTouch = fn;
    }
    
    private onChange(event : any) {
        this.propagateChange(this.value);
    }

И мое использование компонента: .. внутри формы

<input-test2 id="coin" name="coin" [(ngModel)]="manualEntry.coin" #coin="ngModel" required (change)="x($event)" > </input-test2>

У кого-нибудь есть простой пример того, как сделать этот ввод пользовательской формы? Все примеры, которые я нашел, либо сложны, либо не имеют функциональности. Я просто хочу, чтобы для начала по умолчанию вводился type = "text", а затем я мог бы добавить к нему.


person a2ron44    schedule 21.01.2018    source источник
comment
Вы никогда не вызываете PropateChange и PropagateTouch. Вы должны вызывать первое при каждом изменении значения, а второе - при размытии входных данных. Вы также должны обработать отключенное состояние.   -  person JB Nizet    schedule 21.01.2018
comment
вы должны добавить (input) = onChange () в шаблон настраиваемого элемента управления формы   -  person Eliseo    schedule 21.01.2018
comment
Похоже, что размытие и изменение срабатывают одновременно, я не могу заставить сработать одно без другого, это ожидается?   -  person a2ron44    schedule 22.01.2018


Ответы (1)


Спасибо за комментарии выше. Теперь работает как положено. Кажется, это хороший фрагмент, который обеспечивает базовую реализацию input type = "text":

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

@Component({
    selector: 'input-test2',
    template:
        `
           <input type="text" class="form-control" placeholder="Symbol"  [(ngModel)]="value" [maxlength]="5" (change)="onChange($event)" [disabled]="isDisabled" >     
        `,
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => InputTestComponent),
            multi: true
        },
    ]
})
export class InputTestComponent implements ControlValueAccessor {
    @Input('value') value = false;
    
    private propagateChange = (_: any) => { };
    private propagateTouch = (_: any) => { };
    private isDisabled: boolean = false;
    
    constructor(){

    }
    writeValue(value: any): void {
        if (value) {
            this.value = value;
        }
    }
    
    registerOnChange(fn: (_: any) => void): void {
        this.propagateChange = fn;
    }
    registerOnTouched(fn: () => void): void {
        this.propagateTouch = fn;
    }
    
    private onChange(event : any) {
        this.propagateChange(this.value);
    }

    private onTouch(event : any){
        this.propagateTouch(event);
    }

    setDisabledState(isDisabled: boolean): void {
        this.isDisabled = isDisabled;
      }



}

И использование этого компонента можно использовать в такой форме:

<input-test2 
       type="text"  
       id="coin" name="coin"  
       [(ngModel)]="manualEntry.coin"  
       #coin="ngModel" 
       required [disabled]="false" 
       (change)="test($event)">
</input-test2>

Я бы хотел, чтобы по этому поводу были более подробные инструкции, поскольку я считаю, что это довольно распространенная практика создания пользовательских / многоразовых компонентов в формах.

person a2ron44    schedule 21.01.2018
comment
Извините, но это не работает. Когда я меняю значение и отправляю форму, она не имеет значения. - person Pablo; 25.01.2018
comment
Ой, просто добавление (change)="onChange($event)" сработало. Но есть ли другой способ, кроме использования (change)=... - person Pablo; 25.01.2018
comment
Убедитесь, что у вас есть модель ngModel в компоненте, иначе значение не будет сохранено при отправке формы. - person a2ron44; 25.01.2018