Skip to content

Commit

Permalink
feat(timepicker): propagate second as 0 if seconds not displayed
Browse files Browse the repository at this point in the history
also make sure the spinner doesn't stay invalid when hiding invalid seconds

Closes #711
  • Loading branch information
jnizet authored and pkozlowski-opensource committed Sep 12, 2016
1 parent a729ba9 commit c1c68b0
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ export class NgbdTimepickerSeconds {
seconds = true;

toggleSeconds() {
this.seconds = !this.seconds;
this.seconds = !this.seconds;
}
}
91 changes: 91 additions & 0 deletions src/timepicker/timepicker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,95 @@ describe('ngb-timepicker', () => {
expectSameValues(timepicker, config);
});
});

describe('Seconds handling', () => {
it('should propagate seconds to 0 in model if seconds not shown and no second in initial model', async(() => {
const html = `<ngb-timepicker [(ngModel)]="model" [seconds]="false"></ngb-timepicker>`;

const fixture = createTestComponent(html);
fixture.componentInstance.model = {hour: 10, minute: 30};
fixture.detectChanges();
fixture.whenStable()
.then(() => {
fixture.detectChanges();
return fixture.whenStable();
})
.then(() => {
const inputs = fixture.debugElement.queryAll(By.css('input'));

inputs[1].triggerEventHandler('change', createChangeEvent('40'));
fixture.detectChanges();
expectToDisplayTime(fixture.nativeElement, '10:40');
expect(fixture.componentInstance.model).toEqual({hour: 10, minute: 40, second: 0});
});
}));

it('should propagate second as 0 in model if seconds not shown and null initial model', async(() => {
const html = `<ngb-timepicker [(ngModel)]="model" [seconds]="false"></ngb-timepicker>`;

const fixture = createTestComponent(html);
fixture.detectChanges();
fixture.whenStable()
.then(() => {
fixture.detectChanges();
return fixture.whenStable();
})
.then(() => {
const inputs = fixture.debugElement.queryAll(By.css('input'));

inputs[0].triggerEventHandler('change', createChangeEvent('10'));
inputs[1].triggerEventHandler('change', createChangeEvent('40'));
fixture.detectChanges();
expectToDisplayTime(fixture.nativeElement, '10:40');
expect(fixture.componentInstance.model).toEqual({hour: 10, minute: 40, second: 0});
});
}));

it('should leave second as is in model if seconds not shown and second present in initial model', async(() => {
const html = `<ngb-timepicker [(ngModel)]="model" [seconds]="false"></ngb-timepicker>`;

const fixture = createTestComponent(html);
fixture.componentInstance.model = {hour: 10, minute: 30, second: 30};
fixture.detectChanges();
fixture.whenStable()
.then(() => {
fixture.detectChanges();
return fixture.whenStable();
})
.then(() => {
const inputs = fixture.debugElement.queryAll(By.css('input'));

inputs[1].triggerEventHandler('change', createChangeEvent('40'));
fixture.detectChanges();
expectToDisplayTime(fixture.nativeElement, '10:40');
expect(fixture.componentInstance.model).toEqual({hour: 10, minute: 40, second: 30});
});
}));

it('should reset the second to 0 if invalid when seconds are hidden', async(() => {
const html = `<ngb-timepicker [(ngModel)]="model" [seconds]="showSeconds"></ngb-timepicker>`;

const fixture = createTestComponent(html);
fixture.componentInstance.model = {hour: 10, minute: 30, second: null};
fixture.detectChanges();
fixture.whenStable()
.then(() => {
fixture.detectChanges();
return fixture.whenStable();
})
.then(() => {
expectToDisplayTime(fixture.nativeElement, '10:30:');

fixture.componentInstance.showSeconds = false;
fixture.detectChanges();
return fixture.whenStable();
})
.then(() => {
expectToDisplayTime(fixture.nativeElement, '10:30');
expect(fixture.componentInstance.model).toEqual({hour: 10, minute: 30, second: 0});
});
}));
});
});


Expand All @@ -873,5 +962,7 @@ class TestComponent {
disabledForm = new FormGroup({control: new FormControl({value: '', disabled: true})});
submitted = false;

showSeconds = true;

onSubmit() { this.submitted = true; }
}
28 changes: 22 additions & 6 deletions src/timepicker/timepicker.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Component, Input, forwardRef} from '@angular/core';
import {Component, Input, forwardRef, OnChanges, SimpleChanges} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';

import {isNumber, padNumber, toInteger} from '../util/util';
import {isNumber, padNumber, toInteger, isDefined} from '../util/util';
import {NgbTime} from './ngb-time';
import {NgbTimepickerConfig} from './timepicker-config';

Expand Down Expand Up @@ -134,7 +134,8 @@ const NGB_TIMEPICKER_VALUE_ACCESSOR = {
`,
providers: [NGB_TIMEPICKER_VALUE_ACCESSOR]
})
export class NgbTimepicker implements ControlValueAccessor {
export class NgbTimepicker implements ControlValueAccessor,
OnChanges {
disabled: boolean;
model: NgbTime;

Expand Down Expand Up @@ -187,7 +188,12 @@ export class NgbTimepicker implements ControlValueAccessor {
onChange = (_: any) => {};
onTouched = () => {};

writeValue(value) { this.model = value ? new NgbTime(value.hour, value.minute, value.second) : new NgbTime(); }
writeValue(value) {
this.model = value ? new NgbTime(value.hour, value.minute, value.second) : new NgbTime();
if (!this.seconds && (!value || !isNumber(value.second))) {
this.model.second = 0;
}
}

registerOnChange(fn: (value: any) => any): void { this.onChange = fn; }

Expand Down Expand Up @@ -262,8 +268,18 @@ export class NgbTimepicker implements ControlValueAccessor {
*/
formatMinSec(value: number) { return padNumber(value); }

private propagateModelChange() {
this.onTouched();

ngOnChanges(changes: SimpleChanges): void {
if (changes['seconds'] && !this.seconds && this.model && !isNumber(this.model.second)) {
this.model.second = 0;
this.propagateModelChange(false);
}
}

private propagateModelChange(touched = true) {
if (touched) {
this.onTouched();
}
if (this.model.isValid(this.seconds)) {
this.onChange({hour: this.model.hour, minute: this.model.minute, second: this.model.second});
} else {
Expand Down

0 comments on commit c1c68b0

Please sign in to comment.