#angular #angular-directive
#angular #angular-директива
Вопрос:
У меня есть директива для преобразования ввода в верхний регистр
import { Directive, HostListener } from '@angular/core';
@Directive({
selector: '[appUpperCase]',
})
export class UpperCaseInputDirective {
@HostListener('input', ['$event']) onInput(event) {
console.log("UpperCaseInputDirective::event",event);
event.target.value = event.target.value.toUpperCase();
return true;
}
}
Это отлично работает с полями ввода, но теперь я хочу создать пользовательский компонент с некоторым шаблонным кодом вокруг поля ввода
<div class="form-group-basic">
<label [for]="internalId">{{label}}</label>
<mat-form-field floatLabel="always" appearance="outline">
<input
[id]="internalId"
matInput
[formControl]="formControl"
(input)="onInput($event)"
/>
<mat-error *ngIf="formControl.invalid">{{
getErrorMessage(formControl.errors)
}}</mat-error>
</mat-form-field>
</div>
Чтобы получить событие ввода из поля ввода за пределами моего пользовательского компонента, я переслал это событие с помощью EventEmitter
import { Component, EventEmitter, forwardRef, HostBinding, Input, Output } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { translateErrors } from '../../../translation/service/translation.service';
@Component({
selector: 'app-input',
templateUrl: './input.component.html',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => InputComponent),
multi: true
}
]
})
export class InputComponent implements ControlValueAccessor {
@HostBinding('attr.id')
externalId = '';
internalId = '';
@Input()
formControl: FormControl;
@Input()
label: string;
@Input()
set id(value: string) {
this.internalId = value;
this.externalId = null;
}
get id() {
return this.internalId;
}
@Input('value') _value = '';
onChange: any = () => {};
onTouched: any = () => {};
get value():string {
return this._value;
}
set value(value: string) {
this._value = value;
this.onChange(value);
this.onTouched();
}
@Output() input: EventEmitter<any> = new EventEmitter();
control: FormControl;
constructor() {
this.control = new FormControl()
}
registerOnChange(fn) {
this.onChange = fn;
}
writeValue(value) {
if (value) {
this.value = value;
}
}
registerOnTouched(fn) {
this.onTouched = fn;
}
getErrorMessage(errors: object): string {
return translateErrors(errors);
}
onInput(event) {
console.log("inputComponent::onInput",event);
this.input.emit(event);
}
}
Теперь я пытаюсь дать своему пользовательскому компоненту эту директиву:
<app-input id="test-input-field" (input)="onInput($event)" [formControl]="test" appUpperCase label="Test" ></app-input>
Но директива не вызывается. Когда я ввожу символ, я вижу
inputComponent::onInput InputEvent {isTrusted: true, data: "d", isComposing: false, inputType: "insertText", dataTransfer: null, …}
customed.component.ts:94 paymentDetailsFormComponen::onInput InputEvent {isTrusted: true, data: "d", isComposing: false, inputType: "insertText", dataTransfer: null, …}
customed.component.ts:94 paymentDetailsFormComponen::onInput InputEvent {isTrusted: true, data: "d", isComposing: false, inputType: "insertText", dataTransfer: null, …}
Я вижу событие один раз в компоненте InputField и дважды из моего компонента, но обработчик директивы не вызывается. Как я могу этого добиться?
Комментарии:
1. Возможно, у вас ошибка где-то еще в вашем коде. Он отлично работает в этом стекблите, который я только что собрал.
2. @MikeJ Спасибо за подсказку. На первый взгляд я не вижу никакой разницы между вашим StackBlitz и моим приложением. Я думаю, мне нужно взглянуть на это немного глубже.