Можно ли использовать средство форматирования канала Angular внутри элемента управления текстовым полем при редактировании?

Я объявил формат для разделения больших чисел на группы по три цифры и часто использую его таким образом.

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

Теперь есть запрос на соответствующую функциональность, но реализованную в элементе управления вводом, подобном этому.

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

Подход, который я могу придумать, состоит в том, чтобы слушать набор текста и для каждой клавиши выполнять переформатирование содержимого поля следующим образом.

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

Однако, несмотря на то, что этот подход сработает, я не могу перестать задаваться вопросом, не слишком ли много вопросов и ответов, поэтому, прежде чем я построю целую контрольную фауну вокруг этой парадигмы, я хотел бы получить больше информации.

Обычное гугление мало что дало. Однако, учитывая довольно необычный характер требования, его может быть трудно найти.

На данный момент предполагается, что управление вводом не должно использоваться таким образом, что объясняет неуклюжесть моего подхода.

Вы намерены просто отформатировать свой номер как 1,000,123,456.99?

Lea Reimann 11.03.2019 07:29

@LeaReimann Да, за исключением символа-разделителя. Это должно быть пространство. Кроме того, нужны только целые числа. Никаких "центов". Почему вы спрашиваете? Есть ли специальное гладкое решение именно для этого случая?

Konrad Viltersten 11.03.2019 20:34
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
2
2
335
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я думаю, что здесь лучше использовать (атрибут) директива. Вы можете использовать директивы для целей проверки, так почему бы не использовать их для форматирования ваших полей ввода (на самом деле я пытаюсь сделать что-то подобное в моем собственном проекте в данный момент).

В основном это будет выглядеть примерно так (пример из документов angular):

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]. Посмотрите на следующий фрагмент кода и на то, как это делается:

<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>

Интересный подход. Я уже делаю что-то подобное, но как часть всего компонента, а не на инкапсулированном уровне. Так что это определенно хорошие предложения по улучшению. Дополнение к этому. Если я пройду осел, я получу самый ослиный цвет фона. Но компьютер может не знать цвета ослов. Не было бы разумнее отправить код RGB и проверить его с помощью регулярного выражения? Кроме того, я вижу, что вы переходите к родной элемент — не слишком ли неуклюже так крутиться вместо «настоящего» кода Angular (что бы это ни было, хе-хе)?

Konrad Viltersten 10.03.2019 16:05
ElementRef и NativeElement являются частью «настоящего» кода Angular. Конечно, вам не нужно делать это так, но если вы хотите манипулировать чем-либо в шаблоне, вы, вероятно, не сможете сделать это без этих двух.
Lea Reimann 11.03.2019 07:15

Пришел подумать о синтаксисе. Зачем нужны скобки в коде при установке директивы в разметке HTML? Я считаю более естественным перейти на <div myDir>xxx</div>.

Konrad Viltersten 12.03.2019 17:56

Скобки вокруг директивы здесь совершенно необязательны. Вам просто нужно знать разницу между обязательные значения и свойством @Input. Выбирать мудро :)

Lea Reimann 12.03.2019 19:43
Ответ принят как подходящий

Используйте директиву. В стекблиц можно посмотреть как работают.

Директива хранит в переменной "value" строку без пробелов. Каждое изменение происходит (я использую @HotListener(input)) получить позицию курсора, получить значение элемента, удалить пробелы, отформатировать число и поместить курсор в позицию

@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)], также измените значение

Потрясающий ответ. Впрочем, еще две вещи. Во-первых, я считаю, что в коде есть ошибка, потому что, когда я возвращаюсь, я могу удалить только цифры, а когда я дохожу до пробела, дальнейшее удаление не происходит. Во-вторых, я не получил часть с нгконтроль. Не могли бы вы уточнить и, возможно, проиллюстрировать пример для каждого из двух случаев (применение к нгконтроль по сравнению с неконтролируемым).

Konrad Viltersten 10.03.2019 16:25

О ngControl: если вы используете ввод типа <input testPipe [(ngModel)] = "variable">{{variable}} или ReactiveForm <input formControlName = "name1" testPipe >{{myForm?.value.name1}} и не используете setValue, переменная не получит то же значение, которое вы видите. .Если вы введете в конструктор NgControl и попытаетесь применить директиву к обычному вводу <input testPipe>, Angular выдаст вам ошибку, потому что этот ввод не является «NgControl» — по этой причине мы используем @Optional(). Насчет backspace, вы правы, мне нужно подумать об этом. (Я обновил stackblitz, чтобы показать ngControl)

Eliseo 10.03.2019 17:02

Что касается возврата, я думаю, что возврат в «пробел» делает то же самое, что и стрелка влево. Я использую переменную oldValue, чтобы проверить это.

Eliseo 10.03.2019 17:07

Реализация нгонинит существует не просто так, верно? В чем именно причина?

Konrad Viltersten 12.03.2019 18:49

Если сначала вы передаете элементу управления число вроде «123456» и не ставите ngOnInit, значение не форматируется.

Eliseo 12.03.2019 22:53

Другие вопросы по теме