Reputation: 21
I'm trying to create an input that displays a time format but holds a value in minutes. For instance: 1:30 holds a value of 90.
My first option was to use a directive. Now if I change the value in the input to 75 the value displayed should be 1:15. I prefer not to use the @Output and EventEmitter and set up a method to change my value.
Component:
public value = 90;
View:
<p><input [(appTimespan)]="value"></p>
<p>Value: {{ value }}</p>
Directive (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);
}
}
The (display)value of my input is set to '1:15', great... But the value displayed in the view still shows my initial value 90 where I expect it to be 75.
Upvotes: 2
Views: 1738
Reputation: 2165
You can use pipe to show minutes to hours format.
Component:
public value: number = 90;
View:
<input type="number" [(ngModel)]="value" />
<p>Value: {{ value | toTime }}</p>
Pipe:
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);
}
}
Edit You can use same pipe in component for getting hours
submit(){
console.log(this.toTime.transform(this.value))
}
Upvotes: 0
Reputation: 71
You can just use keyUp event, and calculate the time every time you add/delete a number
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);
}
}
This way you dont need any extra code, and the value updates the moment you change it.
Upvotes: 0
Reputation: 57909
I like use @HotListener blur and focus see stackblitz
In blur, you transform the value of the htmlElement. In Focus parse the value. Be carefully, you must use ngOnInit to show the correct value at first time. If we are using the directive in a input [(ngModel)] we must use a setTimeOut -else, the first time not show the correct value-
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]));
}
}
Upvotes: 1