#angular #directive
#angular #директива
Вопрос:
Я пытаюсь создать входные данные, которые отображают формат времени, но содержат значение в минутах. Например: 1:30 содержит значение 90.
Моим первым вариантом было использовать директиву. Теперь, если я изменю значение во входных данных на 75, отображаемое значение должно быть 1: 15. Я предпочитаю не использовать @Output и EventEmitter и настроить метод для изменения моего значения.
Компонент:
public value = 90;
Вид:
<p><input [(appTimespan)]="value"></p>
<p>Value: {{ value }}</p>
Директива (snip):
@Directive({ selector: '[appTimespan]'})
export class TimespanDirective {
@Input( 'appTimespan' ) value: string;
// @Output( 'out' ) update = new EventEmitter();
constructor(private element: ElementRef) {
// just to indicate the directive is applied
element.nativeElement.style.backroundColor = 'yellow';
}
@HostListener('change') onChange() {
// skip the code for calculations and formatting
this.value = 75;
this.element.nativeElement.value = '1:15';
// this.update.emit(75);
}
}
(Отображаемое) значение моего ввода установлено на ‘1: 15’, отлично…
Но значение, отображаемое в представлении, по-прежнему показывает мое начальное значение 90, где я ожидаю, что оно будет 75.
Комментарии:
1. вы хотите отобразить форматированное время в самом вводе или в отдельном div? например, в:
<p>Value: {{ value }}</p>
Как пользователь собирается изменять такие значения, как:1:15, 1,16, etc
или90,91,etc
?2. Если это только w.r.t для отображения, создание простого канала для отображения вычисленного значения должно сработать.
3. Мне нужно значение в компоненте. Я показываю только для отладки. Пользователь может вводить такие значения, как ‘0:45′, ’30’ или даже ‘0.25’. Вычисления не проблема. Пользовательский ввод должен храниться в значении поля компонента в виде числа, а timeformat должен быть «значением» ввода.
Ответ №1:
Мне нравится использовать @HotListener размытие и фокусировку, см. stackblitz
В режиме размытия вы преобразуете значение HTMLElement. В фокусе проанализируйте значение. Будьте осторожны, вы должны использовать ngOnInit, чтобы с первого раза отобразить правильное значение. Если мы используем директиву input [(ngModel)], мы должны использовать setTimeout -иначе в первый раз не будет отображаться правильное значение-
export class TestPipe implements OnInit {
private el: any;
constructor(private elementRef: ElementRef) {
this.el = this.elementRef.nativeElement;
}
@HostListener("focus", ["$event.target.value"])
onFocus() {
this.el.value = this.parse(this.el.value);
}
@HostListener("blur", ["$event.target.value"])
onBlur(value) {
this.el.value = this.transform(value);
}
ngOnInit()
{
setTimeout(()=>{
this.el.value = this.transform(this.el.value);
})
}
transform(value:any)
{
let minutes= value;
let hour=Math.floor(minutes/60);
let rest=minutes%60;
return hour ":" ('00' rest).slice(-2);
}
parse(value:any)
{
let hours=value.split(":");
return '' (( hours[0])*60 ( hours[1]));
}
}
Комментарии:
1. Спасибо. У меня было решение AngularJS, похожее на это. Там я использовал форматеры и анализаторы ngmodel в директиве. Я ищу способ вернуть значение модели в виде числа и отобразить значение на входе в виде строки времени.
Ответ №2:
Вы можете просто использовать событие ввода и вычислять время каждый раз, когда вы добавляете / удаляете число
HTML:
<input type="number" [(ngModel)]="value" (keyup)="changeDisplayValue()" />
<p>Value: {{ displayValue }}</p>
TS:
export class AppComponent {
public value: number = 90;
displayValue: any;
constructor(){
this.displayValue = this.convertTime(this.value);
}
changeDisplayValue(){
this.displayValue = this.convertTime(this.value);
}
convertTime(minutesValue) {
let h = Math.floor(minutesValue / 60);
let m = minutesValue % 60;
return (h < 10 ? '0' h : h) ':' (m < 10 ? '0' m : m);
}
}
Таким образом, вам не нужен дополнительный код, и значение обновляется в тот момент, когда вы его меняете.
Комментарии:
1. Tnx для вашего ввода, но…. Мне действительно нужна (легко повторно используемая) директива / компонент. Таким образом, получается много повторяющегося кода.
Ответ №3:
Вы можете использовать канал для отображения минут в формате часов.
Компонент:
public value: number = 90;
Вид:
<input type="number" [(ngModel)]="value" />
<p>Value: {{ value | toTime }}</p>
Канал:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'toTime'})
export class ToTime implements PipeTransform {
convertMinsToHrsMins(minutes) {
let h:any = Math.floor(minutes / 60);
let m:any = minutes % 60;
h = h < 10 ? '0' h : h;
m = m < 10 ? '0' m : m;
return h ':' m;
}
transform(value: number): string {
return this.convertMinsToHrsMins(value);
}
}
Редактировать
Вы можете использовать один и тот же канал в компоненте для получения часов
submit(){
console.log(this.toTime.transform(this.value))
}
Комментарии:
1. Tnx, но проблема НЕ в форматировании. Мне нужно значение в компоненте.
2. @Elko Вот для чего нужны каналы. Канал в основном используется для преобразования значения в представлении, а не в компоненте
3. @Elko Вы можете использовать один и тот же канал в компоненте, подобном
this.toTime.transform(this.value)
. Я обновил демонстрацию stackblitz, пожалуйста, проверьте.4. Tnx. Опять же, вычисления и форматирование не являются проблемой. Цель состоит в том, чтобы преобразовать обычный текстовый ввод во ввод временного интервала, где значение, отображаемое на входе (после изменения), является форматом времени, а значение модели — в минутах (число).
5. @Javascript Hupp Technologies Да! Точно. Значение модели в минутах и input.value представляют собой строку.