Angular 9 中用于修剪空格的自定义指令
Custom directive for trimming whitespace in Angular 9
我创建了一个自定义指令来从输入框中删除空格,它在 Angular 版本 7 之前完全正常工作,但在 Angular 版本 9 中不起作用。
import {
Directive,
ElementRef,
Output,
EventEmitter,
} from '@angular/core';
@Directive({
selector: '[trim]',
host: {
'(blur)': 'onBlur()'
}
})
export class TrimDirective {
@Output() ngModelChange: EventEmitter < any > = new EventEmitter();
constructor(private element: ElementRef) {}
onBlur() {
(this.element.nativeElement as HTMLInputElement).value = (this.element.nativeElement as HTMLInputElement).value.trim();
this.ngModelChange.emit((this.element.nativeElement as HTMLInputElement).value.trim());
}
}
在模糊事件中它应该trim 空格并更新 ngModel,但它没有更新 ngModel
为了更新输入值,他们同时使用 setProperty() 和 setAttribute()
import { Directive, EventEmitter, Input, ChangeDetectorRef, Output, ElementRef, HostListener, Inject, Renderer2 } from '@angular/core';
import { NgModel } from '@angular/forms';
@Directive({
selector: '[appTrim]'
})
export class TrimDirective {
constructor(
private renderer: Renderer2,
private elementRef: ElementRef,
private ngModel: NgModel) { }
@HostListener("blur")
onBlur() {
let value = this.ngModel.model;
if(value) {
value = value.trim();
this.renderer.setProperty(
this.elementRef.nativeElement, "value", value);
this.renderer.setAttribute(
this.elementRef.nativeElement, "value", value);
this.ngModel.update.emit(value);
} else {
this.renderer.setProperty(
this.elementRef.nativeElement, "value", null);
this.renderer.setAttribute(
this.elementRef.nativeElement, "value", null);
this.ngModel.update.emit("");
}
}
}
示例link
以下是我们的实现方式,从 Angular 4.x 到 11.x
如您所见,我们正在使用选择器,以便将指令应用于所有输入/文本区域元素,而无需显式使用该指令。
这可以很容易地改变,而是使用“app-trim”
import { Directive, HostListener, forwardRef } from "@angular/core";
import { DefaultValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
const TRIM_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TrimValueDirective),
multi: true
};
/**
* The trim accessor for writing trimmed value and listening to changes that is
* used by the {@link NgModel}, {@link FormControlDirective}, and
* {@link FormControlName} directives.
*/
@Directive({
selector: `
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.app-trim-ignore)[formControlName],
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.app-trim-ignore)[formControl],
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.app-trim-ignore)[ngModel],
textarea:not([readonly]):not(.app-trim-ignore)[formControlName],
textarea:not([readonly]):not(.app-trim-ignore)[formControl],
textarea:not([readonly]):not(.app-trim-ignore)[ngModel],
:not([readonly]):not(.app-trim-ignore)[ngDefaultControl],
[app-trim]
`,
providers: [TRIM_VALUE_ACCESSOR]
})
export class TrimValueDirective extends DefaultValueAccessor {
@HostListener("input", ["$event.target.value"])
ngOnChange = (val: string): void => {
this.onChange(val.trim());
};
@HostListener("blur", ["$event.target.value"])
applyTrim(val: string): void {
this.writeValue(val.trim());
}
writeValue(value: any): void {
if (typeof value === "string") {
value = value.trim();
}
super.writeValue(value);
}
}
我创建了一个自定义指令来从输入框中删除空格,它在 Angular 版本 7 之前完全正常工作,但在 Angular 版本 9 中不起作用。
import {
Directive,
ElementRef,
Output,
EventEmitter,
} from '@angular/core';
@Directive({
selector: '[trim]',
host: {
'(blur)': 'onBlur()'
}
})
export class TrimDirective {
@Output() ngModelChange: EventEmitter < any > = new EventEmitter();
constructor(private element: ElementRef) {}
onBlur() {
(this.element.nativeElement as HTMLInputElement).value = (this.element.nativeElement as HTMLInputElement).value.trim();
this.ngModelChange.emit((this.element.nativeElement as HTMLInputElement).value.trim());
}
}
在模糊事件中它应该trim 空格并更新 ngModel,但它没有更新 ngModel
为了更新输入值,他们同时使用 setProperty() 和 setAttribute()
import { Directive, EventEmitter, Input, ChangeDetectorRef, Output, ElementRef, HostListener, Inject, Renderer2 } from '@angular/core';
import { NgModel } from '@angular/forms';
@Directive({
selector: '[appTrim]'
})
export class TrimDirective {
constructor(
private renderer: Renderer2,
private elementRef: ElementRef,
private ngModel: NgModel) { }
@HostListener("blur")
onBlur() {
let value = this.ngModel.model;
if(value) {
value = value.trim();
this.renderer.setProperty(
this.elementRef.nativeElement, "value", value);
this.renderer.setAttribute(
this.elementRef.nativeElement, "value", value);
this.ngModel.update.emit(value);
} else {
this.renderer.setProperty(
this.elementRef.nativeElement, "value", null);
this.renderer.setAttribute(
this.elementRef.nativeElement, "value", null);
this.ngModel.update.emit("");
}
}
}
示例link
以下是我们的实现方式,从 Angular 4.x 到 11.x
如您所见,我们正在使用选择器,以便将指令应用于所有输入/文本区域元素,而无需显式使用该指令。
这可以很容易地改变,而是使用“app-trim”
import { Directive, HostListener, forwardRef } from "@angular/core";
import { DefaultValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
const TRIM_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TrimValueDirective),
multi: true
};
/**
* The trim accessor for writing trimmed value and listening to changes that is
* used by the {@link NgModel}, {@link FormControlDirective}, and
* {@link FormControlName} directives.
*/
@Directive({
selector: `
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.app-trim-ignore)[formControlName],
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.app-trim-ignore)[formControl],
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.app-trim-ignore)[ngModel],
textarea:not([readonly]):not(.app-trim-ignore)[formControlName],
textarea:not([readonly]):not(.app-trim-ignore)[formControl],
textarea:not([readonly]):not(.app-trim-ignore)[ngModel],
:not([readonly]):not(.app-trim-ignore)[ngDefaultControl],
[app-trim]
`,
providers: [TRIM_VALUE_ACCESSOR]
})
export class TrimValueDirective extends DefaultValueAccessor {
@HostListener("input", ["$event.target.value"])
ngOnChange = (val: string): void => {
this.onChange(val.trim());
};
@HostListener("blur", ["$event.target.value"])
applyTrim(val: string): void {
this.writeValue(val.trim());
}
writeValue(value: any): void {
if (typeof value === "string") {
value = value.trim();
}
super.writeValue(value);
}
}