我在实现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
对象中获取它,但是它是空的。我想念什么?
答案 0 :(得分:0)
几个星期前,我对此有疑问,并用一个很好的例子制作了StackBlitz。
希望这可以为您提供帮助吗?
https://stackblitz.com/edit/mat-select-with-controlvalueaccessor