【问题标题】:Custom Component MdDatePicker used in reactive Form以反应形式使用的自定义组件 MdDatePicker
【发布时间】:2018-06-01 19:20:05
【问题描述】:

我正在尝试创建一个自定义组件以用于有角度的 formGroup。

这是我想要使用这个自定义组件的方式:

<form [formGroup]="form">
    ...
    <app-date-picker  formControlName="dateStart"
                  [isConsultation]="isConsultation"
                  [label]="'Du'"
                  [(ngModel)]="agenda.datDeb">
    </app-date-picker>
    ...
</form>

问题:在主组件(包含此表单)中,当我的自定义组件中的值发生更改时,模型不会更新,这涉及 MdDatePicker。虽然我使用的是 ControlValueAccessor。

我的客户组件的 HTML 模板:

<div class="">
    <span *ngIf="label">{{label}} :</span>
    <md-form-field class="" [ngClass]="isConsultation ? 'no-icon' : 'container-input-date'">
        <input mdInput 
           [mdDatepicker]="pickerDebut" 
           class="consultation"
           [(ngModel)]="theDate">
        <md-datepicker-toggle mdSuffix [for]="pickerDebut"></md-datepicker-toggle>
        <md-datepicker #pickerDebut></md-datepicker>
    </md-form-field>
</div>

在您阅读我的组件的打字稿代码之后:

import {Component, Input, ViewChild, forwardRef} from '@angular/core';
import {
  NgModel, 
  ControlValueAccessor, 
  NG_VALUE_ACCESSOR, 
  NG_VALIDATORS,
  FormControl,
} from "@angular/forms";

export function validateDateInputFormat(c: FormControl) {
    // Error content in case input date format is not valid
    let err = {
        formatError: {
            given: c.value,
            acceptedFormat: 'dd/MM/yyyy'
        }
    };

console.log('VALIDATE => c : ', c);

// Control logiq
// return c.value == null ? null : (String(c.value).match(date_regexp)) ? null : err;
return null;
}

@Component({
    selector: 'app-date-picker',
    templateUrl: './date-picker.component.html',
    styleUrls: ['./date-picker.component.scss'],
    providers: [
        {
             provide: NG_VALUE_ACCESSOR,
             useExisting: forwardRef(() => DatePickerComponent),
             multi: true
        },
        {
             provide: NG_VALIDATORS,
             useValue: validateDateInputFormat,
             multi: true
        }
   ]
})
export class DatePickerComponent implements ControlValueAccessor  {

    @Input()
    label : string;
    @Input()
    isConsultation : boolean;

    @ViewChild(NgModel) _theDate: NgModel;

    constructor() { }

    propagateChange = (_: any) => {};
    onTouched: any = () => { };

    writeValue(obj: any): void {
        console.log('writeValue => obj : ', obj);
        if (obj) {
            this._theDate = obj;
        }
    }

    registerOnChange(fn: any): void {
        this.onChange = fn;
        console.log('registerOnChange => fn : ', fn);
    }

    registerOnTouched(fn: any): void {
        this.onTouched = fn;
        console.log('registerOnTouched => fn : ', fn);
    }

    onChange(event){
        console.log('onChange(event) - event => ', event );
        this.propagateChange(event.target.value);
    }

    get theDate() {
        console.log('get theDate()');
        return this._theDate;
    }

    set theDate(val) {
        console.log('set theDate(val) - val => ', val );
        this._theDate = val;
        this.propagateChange(val);
    }
}

我在这里做错了什么?

【问题讨论】:

    标签: angular angular-material angular-material2 angular-reactive-forms reactive-forms


    【解决方案1】:

    我设法克服了这个问题。

    这就是答案。

    第一个问题:

    @ViewChild(NgModel) _theDate: NgModel;
    

    我变成了

    private _theDate : string;
    

    第二个问题: onChange 方法没用。我删除了它,下面是我的组件的结局 TS 代码:

    import {Component, Input, ViewChild, forwardRef} from '@angular/core';
    import {
      NgModel, 
      ControlValueAccessor, 
      NG_VALUE_ACCESSOR, 
      NG_VALIDATORS,
      FormControl,
    } from "@angular/forms";
    
    export function validateDateInputFormat(c: FormControl) {
        // Error content in case input date format is not valid
        let err = {
            formatError: {
                given: c.value,
                acceptedFormat: 'dd/MM/yyyy'
            }
        };
    
    console.log('VALIDATE => c : ', c);
    
    // Control logiq
    // return c.value == null ? null : (String(c.value).match(date_regexp)) ? null : err;
    return null;
    }
    
    @Component({
        selector: 'app-date-picker',
        templateUrl: './date-picker.component.html',
        styleUrls: ['./date-picker.component.scss'],
        providers: [
            {
                 provide: NG_VALUE_ACCESSOR,
                 useExisting: forwardRef(() => DatePickerComponent),
                 multi: true
            },
            {
                 provide: NG_VALIDATORS,
                 useValue: validateDateInputFormat,
                 multi: true
            }
       ]
    })
    export class DatePickerComponent implements ControlValueAccessor  {
    
        @Input()
        label : string;
        @Input()
        isConsultation : boolean;
    
        private _theDate: string;
    
        constructor() { }
    
        propagateChange = (_: any) => {};
        onTouched: any = () => { };
    
        writeValue(obj: any): void {
            console.log('writeValue => obj : ', obj);
            if (obj) {
                this._theDate = obj;
            }
        }
    
        registerOnChange(fn: any): void {
            this.propagateChange= fn;
            console.log('registerOnChange => fn : ', fn);
        }
    
        registerOnTouched(fn: any): void {
            this.onTouched = fn;
            console.log('registerOnTouched => fn : ', fn);
        }
    
        get theDate() {
            console.log('get theDate()');
            return this._theDate;
        }
    
        set theDate(val) {
            console.log('set theDate(val) - val => ', val );
            this._theDate = val;
            this.propagateChange(val);
        }
    }
    

    【讨论】:

    猜你喜欢
    • 2020-04-22
    • 2019-04-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 2021-03-31
    • 1970-01-01
    • 2022-07-08
    相关资源
    最近更新 更多