gpt4 book ai didi

angular - 更新指令中的属性值

转载 作者:太空狗 更新时间:2023-10-29 18:35:32 32 4
gpt4 key购买 nike

我正在尝试创建自己的指令来计算输入长度值。

  • 在 View 初始化时,我在指令中添加了 maxlength 属性,并将值发送到指令 --> ok

  • 在 View 初始化之后,我在我的指令前添加了一个 div,其计数为 0/50 --> ok

我只是在使用键盘时更新长度值时遇到问题(属性已更新但渲染未更新)。你能帮帮我吗?

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'" />

谢谢你的帮助,我迷路了。

最佳答案

Here is a Stackblitz demo指令的

我对您的代码做了一些修改,以下是我的建议:

  • 将您的 appInputMaxLength 类型更改为数字
  • 尽可能多地使用 Renderer2 API,以实现跨平台兼容。
  • 使用私有(private) 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 元素的文本
  • 删除 div 元素,因为 Angular 不会跟踪它。为此你不能使用 this.renderer.removeChild(this.el.nativeElement.parent, this.div) 因为 ngOnDestroy 是在 DOM 被移除并且 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 绑定(bind)到输入时工作并在模型更改时相应地更新,您可以通过注入(inject)主机 ngModel 然后订阅它的 valueChange observable:

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 的输入上使用您的指令:

<input type="text" [appInputMaxLength]="10" [(ngModel)]="value">

关于angular - 更新指令中的属性值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55237224/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com