首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在指令中访问模板驱动模型的角11

在指令中访问模板驱动模型的角11
EN

Stack Overflow用户
提问于 2021-05-12 17:52:19
回答 1查看 180关注 0票数 0

角8.2中,我有一个货币指令,它为用户格式化货币字段,并完美地工作如下:

代码语言:javascript
运行
复制
<input [(ngModel)]="currentEmployment.monthlyIncome" currency>
代码语言:javascript
运行
复制
@Directive({
  selector: '[ngModel][currency]',
  providers: [CurrencyPipe, NgModel],
})
export class CurrencyDirective implements OnDestroy {
  // tracking
  private focused: boolean = false;
  private modelSubscription: Subscription;

  // fraction size
  @Input() size: number = 2;
  // positive only
  @Input() positiveOnly: boolean = false;

  // model update
  @Output() ngModelChange: EventEmitter<any> = new EventEmitter();

  constructor(
    private renderer: Renderer2,
    private el: ElementRef,
    private currencyPipe: CurrencyPipe,
    private model: NgModel
  ) {
    // set mobile keyboard to numpad
    this.renderer.setAttribute(this.el.nativeElement, 'pattern', 'd*');
    // input needs to be text when formatted
    this.renderer.setAttribute(this.el.nativeElement, 'type', 'text');

    // format when model is changed from somewhere else
    this.modelSubscription = this.model.valueChanges.subscribe(value => {
      // dont format while user is editing directly
      if (!this.focused) {
        this.setViewModel(this.currencyPipe.transform(value, this.size));
      }
    });
  }

  ngOnDestroy() {
    // unsubscribe from model subscription
    this.modelSubscription.unsubscribe();
  }

  @HostListener('focus')
  focus() {
    // user is editing, disable formating
    this.focused = true;
    // needs to be type number when unformatted
    this.renderer.setAttribute(this.el.nativeElement, 'type', 'number');
    // set the view model to raw data value
    this.setViewModel(this.model.value);

    // select all in input for easy editing
    $(this.el.nativeElement)
      .one('mouseup', event => {
        event.preventDefault();
      })
      .select();
  }

  @HostListener('blur')
  onBlur() {
    // prepare model value
    let newValue = Number(this.model.value);

    // get absolute value if only positive values are allowed
    if (this.positiveOnly) {
      newValue = Math.abs(this.model.value);
    }

    // emit model change before clearing this.focused
    this.ngModelChange.emit(newValue);
    // input needs to be text when formatted
    this.renderer.setAttribute(this.el.nativeElement, 'type', 'text');
    // format view model
    this.setViewModel(this.currencyPipe.transform(newValue, this.size));
    // clear user focus
    this.focused = false;
  }

  private setViewModel(value: any = null): void {
    if (value !== null) {
      this.el.nativeElement.value = value;
    }
  }
}

然而,当更新到角11.2时,我得到:

errors

  • this.model.value
  • no
      • no

      永远不会被解雇

是否存在某些配置问题,还是模型现在的工作方式不同?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-19 20:47:19

结果,我只需要从提供者中删除NgModel。Angular 9 | ngModel Provider in Directive not working as expected

我不完全明白为什么这会有不同的效果,但这解决了这个问题:

代码语言:javascript
运行
复制
@Directive({
  selector: '[ngModel][currency]',
  providers: [CurrencyPipe],
})
export class CurrencyDirective implements OnDestroy {
  // tracking
  private focused: boolean = false;
  private modelSubscription: Subscription;

  // fraction size
  @Input() size: number = 2;
  // positive only
  @Input() positiveOnly: boolean = false;

  // model update
  @Output() ngModelChange: EventEmitter<any> = new EventEmitter();

  constructor(
    private renderer: Renderer2,
    private el: ElementRef,
    private currencyPipe: CurrencyPipe,
    private model: NgModel
  ) {
    // set mobile keyboard to numpad
    this.renderer.setAttribute(this.el.nativeElement, 'pattern', 'd*');
    // input needs to be text when formatted
    this.renderer.setAttribute(this.el.nativeElement, 'type', 'text');

    // format when model is changed from somewhere else
    this.modelSubscription = this.model.valueChanges.subscribe(value => {
      // dont format while user is editing directly
      if (!this.focused) {
        this.setViewModel(this.currencyPipe.transform(value, this.size));
      }
    });
  }

  ngOnDestroy() {
    // unsubscribe from model subscription
    this.modelSubscription.unsubscribe();
  }

  @HostListener('focus')
  focus() {
    // user is editing, disable formating
    this.focused = true;
    // needs to be type number when unformatted
    this.renderer.setAttribute(this.el.nativeElement, 'type', 'number');
    // set the view model to raw data value
    this.setViewModel(this.model.value);

    // select all in input for easy editing
    $(this.el.nativeElement)
      .one('mouseup', event => {
        event.preventDefault();
      })
      .select();
  }

  @HostListener('blur')
  onBlur() {
    // prepare model value
    let newValue = Number(this.model.value);

    // get absolute value if only positive values are allowed
    if (this.positiveOnly) {
      newValue = Math.abs(this.model.value);
    }

    // emit model change before clearing this.focused
    this.ngModelChange.emit(newValue);
    // input needs to be text when formatted
    this.renderer.setAttribute(this.el.nativeElement, 'type', 'text');
    // format view model
    this.setViewModel(this.currencyPipe.transform(newValue, this.size));
    // clear user focus
    this.focused = false;
  }

  private setViewModel(value: any = null): void {
    if (value !== null) {
      this.el.nativeElement.value = value;
    }
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67508721

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档