"Trim" angular 2 的指令并反映对 ngModel 的更改
"Trim" directive for angular 2 and reflect changes to ngModel
我想创建 Angular 2 指令,该指令仅从用户在输入字段中输入的文本的开头和结尾开始空格。
我有输入框
<input trim name="fruit" [(ngModel)]="fruit"/>
和指令
import {Directive, ElementRef} from "@angular/core";
@Directive({
selector: 'input[trim]',
host: {'(blur)': 'onChange($event)'}
})
export class TrimWhiteSpace {
constructor(private cdRef:ChangeDetectorRef, private el: ElementRef){}
onChange($event:any) {
let theEvent = $event || window.event;
theEvent.target.value = theEvent.target.value.trim();
}
}
工作正常,删除空格并更改输入字段中的文本,但问题是 ngModel 变量 "fruit" 中的值没有更改,它仍然包含开头或结尾带有空格的文本.
我还尝试在 onChange 方法中添加以下内容
this.el.nativeElement.value = theEvent.trim();
this.cdRef.detectChanges();
并将形式 (blur) 更改为 (ngModelChange),但 ngModel 中的文本不受影响。
有什么建议吗?
你看过https://github.com/anein/angular2-trim-directive了吗?
它似乎可以解决您的用例
@ErVipinSharma 我将文件 src/input-trim.directive.ts 更改为 github,您可以在上面的 link 中找到它。在这个文件中,我删除了 method
@HostListener( 'input', ['$event.type', '$event.target.value'] )
onInput( event: string, value: string ): void {
this.updateValue( event, value );
}
并添加了方法
@HostListener('paste', ['$event', '$event.target'])
onPaste($event: any, target: any) {
// do something when on paste event happens
}
为了避免混淆更改模型属性名称。
<input name="fruit" [(ngModel)]="fruit1" (change)="fruit1=fruit1.trim()"/>
虽然晚了一年多,但你不妨试试https://www.npmjs.com/package/ngx-trim-directive
它基于一个简单的事实,即 Angular 监听输入事件以实现视图到模型的绑定。
演示:https://angular-86w6nm.stackblitz.io, editor: https://stackblitz.com/edit/angular-86w6nm
示例中的 CommonController 只是基础 class,它触发 onDestroy 挂钩中的主题以取消订阅 observable。
@Directive({
selector: '[appTrimOnBlur]'
})
export class TrimOnBlurDirective extends CommonController implements OnInit {
constructor(private elementRef: ElementRef,
@Self() private ngControl: NgControl) {
super();
}
ngOnInit(): void {
fromEvent(this.elementRef.nativeElement, 'blur').pipe(
takeUntil(this.unsubscribeOnDestroy)
).subscribe(() => {
const currentValue: string = this.ngControl.value.toString();
const whitespace: string = ' ';
if (currentValue.startsWith(whitespace) || currentValue.endsWith(whitespace)) {
this.ngControl.control.patchValue(currentValue.trim());
}
});
}
}
您可以创建通用 trim 指令,这将使 trim 不仅适用于模糊事件,而且适用于您将提供的任何事件:
@Input() public trimEventName: string = 'blur';
constructor(private elementRef: ElementRef,
@Self() private ngControl: NgControl) {
super();
}
ngOnInit(): void {
fromEvent(this.elementRef.nativeElement, this.trimEventName).pipe(
takeUntil(this.unsubscribeOnDestroy)
).subscribe(() => {
const currentValue: string = this.ngControl.value.toString();
const whitespace: string = ' ';
if (currentValue.startsWith(whitespace) || currentValue.endsWith(whitespace)) {
this.ngControl.control.patchValue(currentValue.trim());
}
});
}
以下指令可以与 Reactive-Forms 一起用于 trim 所有表单字段:
@Directive({
selector: '[formControl], [formControlName]',
})
export class TrimFormFieldsDirective {
@Input() type: string;
constructor(@Optional() private formControlDir: FormControlDirective,
@Optional() private formControlName: FormControlName) {}
@HostListener('blur')
@HostListener('keydown.enter')
trimValue() {
const control = this.formControlDir?.control || this.formControlName?.control;
if (typeof control.value === 'string' && this.type !== 'password') {
control.setValue(control.value.trim());
}
}
}
我真的很喜欢这个指令,因为它会自动应用于几乎所有内容:
import { Directive, forwardRef, HostListener } from '@angular/core';
import { DefaultValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const TRIM_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TrimValueAccessorDirective),
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({
// eslint-disable-next-line @angular-eslint/directive-selector
selector: `
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.ng-trim-ignore)[formControlName],
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.ng-trim-ignore)[formControl],
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.ng-trim-ignore)[ngModel],
textarea:not([readonly]):not(.ng-trim-ignore)[formControlName],
textarea:not([readonly]):not(.ng-trim-ignore)[formControl],
textarea:not([readonly]):not(.ng-trim-ignore)[ngModel],
:not([readonly]):not(.ng-trim-ignore)[ngDefaultControl]'
`,
providers: [TRIM_VALUE_ACCESSOR],
})
export class TrimValueAccessorDirective extends DefaultValueAccessor {
@HostListener('input', ['$event.target.value'])
ngOnChange = (val: string) => {
this.onChange(val.trim());
};
@HostListener('blur', ['$event.target.value'])
applyTrim(val: string) {
this.writeValue(val.trim());
}
writeValue(value: any): void {
if (typeof value === 'string') {
value = value.trim();
}
super.writeValue(value);
}
}
从这里开始:https://medium.com/@rm.dev/angular-auto-trim-your-input-string-using-angular-directive-5ae72b8cee9d
如果您将 https://github.com/anein/angular2-trim-directive 与 <input trim="blur" ...>
一起使用,它将允许中间空格。
我想创建 Angular 2 指令,该指令仅从用户在输入字段中输入的文本的开头和结尾开始空格。
我有输入框
<input trim name="fruit" [(ngModel)]="fruit"/>
和指令
import {Directive, ElementRef} from "@angular/core";
@Directive({
selector: 'input[trim]',
host: {'(blur)': 'onChange($event)'}
})
export class TrimWhiteSpace {
constructor(private cdRef:ChangeDetectorRef, private el: ElementRef){}
onChange($event:any) {
let theEvent = $event || window.event;
theEvent.target.value = theEvent.target.value.trim();
}
}
工作正常,删除空格并更改输入字段中的文本,但问题是 ngModel 变量 "fruit" 中的值没有更改,它仍然包含开头或结尾带有空格的文本.
我还尝试在 onChange 方法中添加以下内容
this.el.nativeElement.value = theEvent.trim();
this.cdRef.detectChanges();
并将形式 (blur) 更改为 (ngModelChange),但 ngModel 中的文本不受影响。
有什么建议吗?
你看过https://github.com/anein/angular2-trim-directive了吗?
它似乎可以解决您的用例
@ErVipinSharma 我将文件 src/input-trim.directive.ts 更改为 github,您可以在上面的 link 中找到它。在这个文件中,我删除了 method
@HostListener( 'input', ['$event.type', '$event.target.value'] )
onInput( event: string, value: string ): void {
this.updateValue( event, value );
}
并添加了方法
@HostListener('paste', ['$event', '$event.target'])
onPaste($event: any, target: any) {
// do something when on paste event happens
}
为了避免混淆更改模型属性名称。
<input name="fruit" [(ngModel)]="fruit1" (change)="fruit1=fruit1.trim()"/>
虽然晚了一年多,但你不妨试试https://www.npmjs.com/package/ngx-trim-directive
它基于一个简单的事实,即 Angular 监听输入事件以实现视图到模型的绑定。
演示:https://angular-86w6nm.stackblitz.io, editor: https://stackblitz.com/edit/angular-86w6nm
示例中的 CommonController 只是基础 class,它触发 onDestroy 挂钩中的主题以取消订阅 observable。
@Directive({
selector: '[appTrimOnBlur]'
})
export class TrimOnBlurDirective extends CommonController implements OnInit {
constructor(private elementRef: ElementRef,
@Self() private ngControl: NgControl) {
super();
}
ngOnInit(): void {
fromEvent(this.elementRef.nativeElement, 'blur').pipe(
takeUntil(this.unsubscribeOnDestroy)
).subscribe(() => {
const currentValue: string = this.ngControl.value.toString();
const whitespace: string = ' ';
if (currentValue.startsWith(whitespace) || currentValue.endsWith(whitespace)) {
this.ngControl.control.patchValue(currentValue.trim());
}
});
}
}
您可以创建通用 trim 指令,这将使 trim 不仅适用于模糊事件,而且适用于您将提供的任何事件:
@Input() public trimEventName: string = 'blur';
constructor(private elementRef: ElementRef,
@Self() private ngControl: NgControl) {
super();
}
ngOnInit(): void {
fromEvent(this.elementRef.nativeElement, this.trimEventName).pipe(
takeUntil(this.unsubscribeOnDestroy)
).subscribe(() => {
const currentValue: string = this.ngControl.value.toString();
const whitespace: string = ' ';
if (currentValue.startsWith(whitespace) || currentValue.endsWith(whitespace)) {
this.ngControl.control.patchValue(currentValue.trim());
}
});
}
以下指令可以与 Reactive-Forms 一起用于 trim 所有表单字段:
@Directive({
selector: '[formControl], [formControlName]',
})
export class TrimFormFieldsDirective {
@Input() type: string;
constructor(@Optional() private formControlDir: FormControlDirective,
@Optional() private formControlName: FormControlName) {}
@HostListener('blur')
@HostListener('keydown.enter')
trimValue() {
const control = this.formControlDir?.control || this.formControlName?.control;
if (typeof control.value === 'string' && this.type !== 'password') {
control.setValue(control.value.trim());
}
}
}
我真的很喜欢这个指令,因为它会自动应用于几乎所有内容:
import { Directive, forwardRef, HostListener } from '@angular/core';
import { DefaultValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const TRIM_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TrimValueAccessorDirective),
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({
// eslint-disable-next-line @angular-eslint/directive-selector
selector: `
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.ng-trim-ignore)[formControlName],
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.ng-trim-ignore)[formControl],
input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.ng-trim-ignore)[ngModel],
textarea:not([readonly]):not(.ng-trim-ignore)[formControlName],
textarea:not([readonly]):not(.ng-trim-ignore)[formControl],
textarea:not([readonly]):not(.ng-trim-ignore)[ngModel],
:not([readonly]):not(.ng-trim-ignore)[ngDefaultControl]'
`,
providers: [TRIM_VALUE_ACCESSOR],
})
export class TrimValueAccessorDirective extends DefaultValueAccessor {
@HostListener('input', ['$event.target.value'])
ngOnChange = (val: string) => {
this.onChange(val.trim());
};
@HostListener('blur', ['$event.target.value'])
applyTrim(val: string) {
this.writeValue(val.trim());
}
writeValue(value: any): void {
if (typeof value === 'string') {
value = value.trim();
}
super.writeValue(value);
}
}
从这里开始:https://medium.com/@rm.dev/angular-auto-trim-your-input-string-using-angular-directive-5ae72b8cee9d
如果您将 https://github.com/anein/angular2-trim-directive 与 <input trim="blur" ...>
一起使用,它将允许中间空格。