【问题标题】:Possible to use pipe formatter of Angular inside textbox control while editing?编辑时可以在文本框控件内使用 Angular 的管道格式化程序吗?
【发布时间】:2019-03-10 09:55:13
【问题描述】:

我已经声明了一种将大数分成三位数组的格式,并经常像这样使用它。

<div>Huge number: {{ i_am_huge | make_threesome }}</div>

现在,有一个相应功能的请求,但在像这样的输入控件中实现。

<input id="numeroUno"
       type="text">

我能想到的方法是听打字并为每个键执行重新格式化框的内容,就像这样。

<input id="numeroUno"
       type="text"
       (keyup)="formatify">

然而,虽然这种方法可行,但我不禁怀疑这是否过于 Q&D,所以在我围绕这个范式建立一个完整的控制群之前,我想了解更多信息。

通常的谷歌搜索并没有给我太多帮助。但是,给出一个相当不寻常的要求,可能很难找到。

此时的假设是输入控件不应该以这种方式使用,这解释了我的方法的笨拙。

【问题讨论】:

  • 你的意图只是像1,000,123,456.99这样格式化你的号码吗?
  • @LeaReimann 是的,分隔符除外。应该是空间此外,只需要整数。没有“分”。你为什么要问?是否有针对这种情况的特殊情况平滑解决方案?

标签: html angular input format


【解决方案1】:

使用指令。在stackblitz 你可以看到它是如何工作的。

该指令将不带空格的字符串存储在变量“value”中。每次发生变化(我使用@HotListener(输入))获取光标的位置,获取元素的值,删除空格,格式化数字并将光标放在该位置

@Directive({ selector: "[testPipe]" })
export class TestPipe  implements OnInit {

  private el: HTMLInputElement;
  private value: any;
  constructor(@Optional() private ngControl:NgControl,
                private elementRef: ElementRef) {
    this.el = this.elementRef.nativeElement;
  }
  @HostListener("input", ["$event.target.value"])
  onInput() {
    let pos = this.el.selectionStart; //get the position of the cursor
    this.value = this.el.value.replace(/ /gi, ""); //store the value without spaces
    if (this.value.length%3==1) //If we must add an extra space
      pos++;
    //Yes, it's a "bizarro" way to separate in group of three 
    this.el.value=this.value.match(/(.+?)(?=(.{3})+(?!.)|$)/g).join(' ');
    //this.el.value=this.value.match(/(\d+?)(?=(\d{3})+(?!\d)|$)/g).join(' ');
    //Finally give the position of cursor
    this.el.selectionStart = this.el.selectionEnd = pos;
    if (this.ngControl)
        this.ngControl.control.setValue(this.el.value,{emit:false})

  }
  ngOnInit()
  {
    this.value = this.el.value.replace(/ /gi, "");
    this.el.value=this.value.match(/(.+?)(?=(.{3})+(?!.)|$)/g).join(' ');
//  this.el.value=this.value.match(/(\d+?)(?=(\d{3})+(?!\d)|$)/g).join(' ');
    if (this.ngControl)
        this.ngControl.control.setValue(this.el.value,{emit:false})

  }
}

更新我在构造函数中添加了一个@Optional() ngControl:NgControl,所以,如果指令应用于一个ngControl(输入属于一个formGroup或有一个[(ngModel)],也改变值

【讨论】:

  • 很棒的答案。不过还有两件事。首先,我认为代码中存在错误,因为当我退格时,我只能删除数字,当我到达空格时,不会进一步删除。其次,我没有得到 ngControl 的部分。您是否愿意为这两种情况(应用到 ngControl 与非控制)中的每一种情况详细说明并举例说明。
  • 关于 ngControl:如果您使用 &lt;input testPipe [(ngModel)]="variable"&gt;{{variable}} 之类的输入或使用 ReactiveForm &lt;input formControlName="name1" testPipe &gt;{{myForm?.value.name1}} 而不使用 setValue,则变量不会获得与您看到的相同的值。 . 如果你注入构造函数 NgControl 并尝试将指令应用于普通输入 &lt;input testPipe&gt;,Angular 会给你一个错误,因为这个输入不是“NgControl”——这就是我们使用 @Optional() 的原因。关于退格,你是对的,我需要考虑一下。 (我已经更新了 stackblitz 以显示 ngControl)
  • 关于退格,我想“空格”中的退格与左箭头相同。我使用变量 oldValue 来检查这一点。
  • ngOnInit 的实现是有原因的,对吧?究竟是什么原因?
  • 如果一开始,你给控件输入一个像“123456”这样的数字,而不是把ngOnInit,这个值没有格式化
【解决方案2】:

我认为您应该在这里使用(attribute) directive。您可以将指令用于验证目的,所以为什么不使用它在您的输入字段中进行格式化(实际上目前正在我自己的项目中尝试做类似的事情)。

基本上看起来有点像(角度文档中的示例):

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  constructor(private el: ElementRef) { }

  @Input('appHighlight') highlightColor: string;

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor || 'red');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}

通过这种方式,您可以操作输入字段内的值并监听像click 这样的事件。

在它起作用之前您必须做的另一件事:将指令(与[ngStyle] 或[ngClass] 非常相似)添加到您通过[your-directives-name] 提交的输入中。看看下面的代码 sn-p 以及它是如何完成的:

<h1>My First Attribute Directive</h1>

<h4>Pick a highlight color</h4>
<div>
  <input type="radio" name="colors" (click)="color='lightgreen'">Green
  <input type="radio" name="colors" (click)="color='yellow'">Yellow
  <input type="radio" name="colors" (click)="color='cyan'">Cyan
</div>
<p [appHighlight]="color">Highlight me!</p>

【讨论】:

  • 有趣的方法。我已经在做类似的事情,但作为整个组件的一部分,而不是封装级别,所以这绝对是一个很好的改进建议。后续行动。如果我传入 donkey 我将得到最驴的背景颜色。但是计算机可能不知道驴的颜色。发送 RGB 代码并使用正则表达式验证它不是更有意义吗?另外,我看到你进入 nativeElement - 像这样到处乱跑而不是“真正的” Angular 代码(不管那可能是什么,呵呵)是不是有点笨拙?
  • ElementRef 和 NativeElement 是“真正的”Angular 代码的一部分。当然,你不需要那样做,但如果你想操作模板中的任何东西,没有这两个你可能无法做到。
  • 开始思考语法。在 HTML 标记中设置指令时,为什么我们需要代码中的括号?我会觉得去
    xxx
    更自然。
  • 指令周围的括号在这里是完全可选的。您只需要知道binding values 与@Input 属性的区别。明智地选择:)
猜你喜欢
  • 1970-01-01
  • 2017-03-09
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多