从不同的组件访问ControlValueAccessor

时间:2018-10-28 18:52:36

标签: javascript angular typescript angular2-forms controlvalueaccessor

我在实现ControlValueAccessor的地方有组件,但是在理解正确的使用方式时遇到了问题:

import { Component, OnInit, forwardRef, Output, EventEmitter, OnChanges, Input, ViewChild } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { UserOrEmail } from '../entities/UserOrEmail';

export const USER_INPUT_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    // tslint:disable-next-line
    useExisting: forwardRef(() => AddUserOrEmailComponent),
    multi: true,
};

const noop = () => {
    // Placeholder operation
};
@Component({
    selector: 'app-add-user-or-email',
    templateUrl: './add-user-or-email.component.html',
    providers: [USER_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class AddUserOrEmailComponent implements OnInit, ControlValueAccessor {
    @Input()
    user: any = UserOrEmail;

    @Output()
    change: EventEmitter<UserOrEmail> = new EventEmitter<UserOrEmail>();

    users: any = [];
    ngOnInit() {
        this.user = {
            userId: 'ull',
            name: 'null',
            email: 'null'
        };
        this.users = ConstantService.UserArray;
    }

    // #region [ Value Accessor Interface ]--------------------------------------------------------

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

    get value(): any {
        return this.user;
    }

    // [ ControlValueAccessor interface implementation ]-------------------------------------------
    set value(v: any) {
        if (this.user !== v) {
            this.user = <UserOrEmail>v;
            this.onChangeCallback(v);
            this.change.next(this.user);
        }
    }

    writeValue(value: any) {
        if (value !== this.user)
            this.user = <UserOrEmail>value;
    }

    registerOnChange(fn: any) {
        this.onChangeCallback = fn;
    }

    registerOnTouched(fn: any) {
        this.onTouchedCallback = fn;
    }
}

和html:

<div>
    <div class="form-column">
        <div class="form-row">
            <label>
                {{'GENERIC.USER'|translate}}
            </label>
            <select>
                <option [ngValue]="'default'"></option>
                <option *ngFor="let user of users" [ngValue]="user">{{user.login}}</option>
            </select>
        </div>
        <div class="form-row">
            <label for="addPersonEmail" >{{'GENERIC.EMAIL' | translate}}</label>
            <input type="email"  placeholder="{{'GENERIC.EMAIL'|translate}}" pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$">
        </div>
    </div>
</div>

我尝试在另一个组件中使用它:

hmtl:

<app-modal class="form" #addMilestoneModal [width]="550">
    <div header>{{'MODALS.ADD_MILESTONE'|translate}}</div>
    <div body>
        <div class="form-column">
            <div class="form-value">
                <app-add-user-or-email #addUser [(ngModel)]="milestone.assignee"></app-add-user-or-email>
            </div>
            <div class="form-row">
                <label for="addMilestoneDescription">{{'GENERIC.DESCRIPTION' | translate}}</label>
                <textarea style="height: 150px" [(ngModel)]="milestone.description"></textarea>
            </div>

        </div>
    </div>
    <div footer class="flex-container">
        <button class="flex-item-row btn btn-a" [disabled]="!milestone.description" (click)="apply()">{{'GENERIC.APPLY'
            | translate}}</button>
    </div>
</app-modal>

打字稿:

import { Component, ViewChild, EventEmitter } from '@angular/core';
import { ModalComponent } from '../../widgets/modal/modal.component';
import { Milestone } from '../../entities/Milestone';
import { ConstantService } from '../../services/ConstantService';
import { AddUserOrEmailComponent } from '../../add-user-or-email/add-user-or-email.component';

@Component({
  selector: 'app-add-milestone-modal',
  templateUrl: './add-milestone-modal.component.html'
})
export class AddMilestoneModalComponent {

  @ViewChild('addMilestoneModal')
  modal: ModalComponent;

  cs = ConstantService;

  emitter: EventEmitter<Milestone> = new EventEmitter<Milestone>();

  milestone: any = Milestone;
  apply() {
    console.log(this.milestone); // <---- HERE IT SHOULD BE ACCESSED
    debugger;
    this.emitter.next(this.milestone);
    this.modal.close();
  }

  cancel() {
    this.emitter.next(null);
    this.modal.close();
  }
}

我应该在milestone对象中获取它,但是它是空的。我想念什么?

1 个答案:

答案 0 :(得分:0)

几个星期前,我对此有疑问,并用一个很好的例子制作了StackBlitz。

希望这可以为您提供帮助吗?

https://stackblitz.com/edit/mat-select-with-controlvalueaccessor