我正在尝试创建自己的指令以计算输入长度值。
在视图初始化上,我在指令中添加了maxlength属性,并将其值发送给指令->确定
在视图初始化之后,我在指令之前添加了一个div,其计数为0/50->确定
当我使用键盘时,我只是有一个更新长度值的问题(属性是更新的,而不是渲染的)。 你能帮我吗?
import {
AfterViewInit,
Directive, ElementRef, HostListener, Input, OnInit, Renderer2
} from '@angular/core';
@Directive({
selector: '[appInputmaxLength]'
})
export class InputmaxLengthDirective implements OnInit, AfterViewInit {
@Input() appInputmaxLength: string;
private currentValue = 0;
constructor(
private el: ElementRef,
private renderer: Renderer2
) {}
@HostListener('keydown') isChange() {
let countNb = this.el.nativeElement.value.length + 1;
if (countNb <= 1) {
this.currentValue = 0;
} else {
this.currentValue = countNb;
}
console.log('test: ', this.el.nativeElement.value.length + 1);
}
ngOnInit() {
this.renderer.setAttribute(this.el.nativeElement, 'maxLength', this.appInputmaxLength);
}
ngAfterViewInit() {
const html = '<div>' + this.currentValue + ' / ' + this.appInputmaxLength + '</div>'
const target = this.el;
target.nativeElement.insertAdjacentHTML('afterEnd', html);
}
}
这是我使用指令的方式:
<input type="text" [appInputmaxLength]="'5'" />
感谢您的帮助,我迷路了。
答案 0 :(得分:1)
我对您的代码做了一些修改,这是我的建议:
appInputMaxLength
类型更改为数字Renderer2
API,使其跨平台兼容。div
属性来保存div并稍后进行更新,并使用this.renderer.createElement('div')
创建它this.renderer.insertBefore(this.el.nativeElement.parentNode, this.div, this.el.nativeElement.nextSibling)
将其插入到主机之后input
事件收听更改,并从事件中获取值,然后获取其长度并更新div
currentValue
变量,只需从输入值或事件中获取长度即可。this.renderer.setProperty(this.div, 'innerText', ...);
更新div元素的文本this.renderer.removeChild(this.el.nativeElement.parent, this.div)
,因为在删除DOM之后将调用ngOnDestroy
,并且parent
引用将为空。您必须直接致电this.div.remove()
(see this github issue)。
import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnInit, Renderer2, OnDestroy } from '@angular/core';
@Directive({
selector: '[appInputMaxLength]'
})
export class InputMaxLengthDirective implements OnInit, AfterViewInit, OnDestroy {
@Input() appInputMaxLength: number;
private div: HTMLDivElement;
constructor(private el: ElementRef, private renderer: Renderer2) {}
@HostListener('input', ['$event']) onChange(event) {
this.update(event.target.value.length);
}
ngOnInit() {
this.renderer.setAttribute(this.el.nativeElement, 'maxLength', this.appInputMaxLength.toString());
}
ngOnDestroy() {
if (this.div) {
this.div.remove();
}
}
ngAfterViewInit() {
this.div = this.renderer.createElement('div');
this.renderer.insertBefore(this.el.nativeElement.parentNode, this.div, this.el.nativeElement.nextSibling);
this.update(this.el.nativeElement.value.length);
}
private update(length: number) {
this.renderer.setProperty(this.div, 'innerText', `${length} / ${this.appInputMaxLength}`);
}
}
像这样使用它,并输入数字:
<input type="text" [appInputMaxLength]="10">
如果您希望指令在将ngModel
绑定到输入时起作用,并且在模型更改时进行相应更新,则可以通过注入主机ngModel
并订阅其{{1 }}可观察:
valueChange
然后,您可以在带有import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnInit, Renderer2, Optional, OnDestroy } from '@angular/core';
import { NgModel } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Directive({
selector: '[appInputMaxLength]'
})
export class InputMaxLengthDirective implements OnInit, AfterViewInit, OnDestroy {
@Input() appInputMaxLength: number;
private div: HTMLDivElement;
private destroyed$ = new Subject();
constructor(private el: ElementRef, private renderer: Renderer2, @Optional() private ngModel: NgModel) {}
@HostListener('input', ['$event']) onChange(event) {
if (!this.ngModel) {
this.update(event.target.value.length);
}
}
ngOnInit() {
this.renderer.setAttribute(this.el.nativeElement, 'maxLength', this.appInputMaxLength.toString());
if (this.ngModel) {
this.ngModel.valueChanges.pipe(takeUntil(this.destroyed$)).subscribe(value => {
this.update(value.length);
})
}
}
ngAfterViewInit() {
this.div = this.renderer.createElement('div');
this.renderer.insertBefore(this.el.nativeElement.parentNode, this.div, this.el.nativeElement.nextSibling);
this.update(this.el.nativeElement.value.length);
}
ngOnDestroy() {
this.destroyed$.next();
this.destroyed$.complete();
if (this.div) {
this.div.remove();
}
}
private update(length: number) {
this.renderer.setProperty(this.div, 'innerText', `${length} / ${this.appInputMaxLength}`);
}
}
的输入上使用指令:
ngModel
答案 1 :(得分:0)
尝试此代码,我已经重写了一些代码
import {
AfterViewInit,
Directive,
ElementRef,
HostListener,
Input,
OnInit,
Renderer2,
OnDestroy
} from '@angular/core';
@Directive({
selector: '[appInputmaxLength]'
})
export class InputmaxLengthDirective implements OnInit, AfterViewInit, OnDestroy {
@Input() appInputmaxLength: string;
private currentValue = 0;
countDiv: HTMLDivElement;
parent: any;
constructor(private el: ElementRef<HTMLInputElement>, private renderer: Renderer2) {}
@HostListener('keyup') isChange() {
const countNb = this.el.nativeElement.value.length + 1;
if (countNb <= 1) {
this.currentValue = 0;
this.updateCount();
} else {
this.currentValue = countNb;
this.updateCount();
}
console.log('test: ', this.el.nativeElement.value.length + 1);
}
ngOnInit() {
this.renderer.setAttribute(this.el.nativeElement, 'maxLength', this.appInputmaxLength);
}
ngOnDestroy() {
this.renderer.removeChild(this.parent, this.countDiv);
this.renderer.destroyNode(this.countDiv);
}
updateCount() {
this.countDiv.innerText = this.currentValue + ' / ' + this.appInputmaxLength;
}
ngAfterViewInit() {
this.countDiv = this.renderer.createElement('div');
this.parent = this.renderer.parentNode(this.el.nativeElement);
this.renderer.appendChild(parent, this.countDiv);
this.updateCount();
}
}
在这段代码中,我使用渲染器创建div元素,并在currentValue
发生更改的地方更新其值。
还必须在销毁指令时销毁它,以避免内存泄漏
答案 2 :(得分:0)
正确的方法是使用二传手。每次输入更改时,都会调用setter函数。
@Input() set appInputmaxLength(value:string){
// Your code here
console.log(value);
}
可以在此处找到示例:https://angular.io/guide/structural-directives(您的指令不是结构性指令,但在此示例中是
)