Я объявил формат для разделения больших чисел на группы по три цифры и часто использую его таким образом.
<div>Huge number: {{ i_am_huge | make_threesome }}</div>
Теперь есть запрос на соответствующую функциональность, но реализованную в элементе управления вводом, подобном этому.
<input id = "numeroUno"
type = "text">
Подход, который я могу придумать, состоит в том, чтобы слушать набор текста и для каждой клавиши выполнять переформатирование содержимого поля следующим образом.
<input id = "numeroUno"
type = "text"
(keyup) = "formatify">
Однако, несмотря на то, что этот подход сработает, я не могу перестать задаваться вопросом, не слишком ли много вопросов и ответов, поэтому, прежде чем я построю целую контрольную фауну вокруг этой парадигмы, я хотел бы получить больше информации.
Обычное гугление мало что дало. Однако, учитывая довольно необычный характер требования, его может быть трудно найти.
На данный момент предполагается, что управление вводом не должно использоваться таким образом, что объясняет неуклюжесть моего подхода.
@LeaReimann Да, за исключением символа-разделителя. Это должно быть пространство. Кроме того, нужны только целые числа. Никаких "центов". Почему вы спрашиваете? Есть ли специальное гладкое решение именно для этого случая?






Я думаю, что здесь лучше использовать (атрибут) директива. Вы можете использовать директивы для целей проверки, так почему бы не использовать их для форматирования ваших полей ввода (на самом деле я пытаюсь сделать что-то подобное в моем собственном проекте в данный момент).
В основном это будет выглядеть примерно так (пример из документов 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 (что бы это ни было, хе-хе)?
ElementRef и NativeElement являются частью «настоящего» кода Angular. Конечно, вам не нужно делать это так, но если вы хотите манипулировать чем-либо в шаблоне, вы, вероятно, не сможете сделать это без этих двух.
Пришел подумать о синтаксисе. Зачем нужны скобки в коде при установке директивы в разметке HTML? Я считаю более естественным перейти на <div myDir>xxx</div>.
Скобки вокруг директивы здесь совершенно необязательны. Вам просто нужно знать разницу между обязательные значения и свойством @Input. Выбирать мудро :)
Используйте директиву. В стекблиц можно посмотреть как работают.
Директива хранит в переменной "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)], также измените значение
Потрясающий ответ. Впрочем, еще две вещи. Во-первых, я считаю, что в коде есть ошибка, потому что, когда я возвращаюсь, я могу удалить только цифры, а когда я дохожу до пробела, дальнейшее удаление не происходит. Во-вторых, я не получил часть с нгконтроль. Не могли бы вы уточнить и, возможно, проиллюстрировать пример для каждого из двух случаев (применение к нгконтроль по сравнению с неконтролируемым).
О ngControl: если вы используете ввод типа <input testPipe [(ngModel)] = "variable">{{variable}} или ReactiveForm <input formControlName = "name1" testPipe >{{myForm?.value.name1}} и не используете setValue, переменная не получит то же значение, которое вы видите. .Если вы введете в конструктор NgControl и попытаетесь применить директиву к обычному вводу <input testPipe>, Angular выдаст вам ошибку, потому что этот ввод не является «NgControl» — по этой причине мы используем @Optional(). Насчет backspace, вы правы, мне нужно подумать об этом. (Я обновил stackblitz, чтобы показать ngControl)
Что касается возврата, я думаю, что возврат в «пробел» делает то же самое, что и стрелка влево. Я использую переменную oldValue, чтобы проверить это.
Реализация нгонинит существует не просто так, верно? В чем именно причина?
Если сначала вы передаете элементу управления число вроде «123456» и не ставите ngOnInit, значение не форматируется.
Вы намерены просто отформатировать свой номер как
1,000,123,456.99?