Skip to content

Commit e7611ce

Browse files
committed
fix(MdInput): Add a test and convert values entered based on the type of the md-input
1 parent 6cb7b9b commit e7611ce

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

src/components/input/input.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
[type]="type"
2121
(focus)="onFocus()"
2222
(blur)="onBlur()"
23-
[(ngModel)]="value">
23+
[(ngModel)]="value"
24+
(change)="onChange($event)">
2425

2526
<label class="md-input-placeholder"
2627
[attr.for]="id"

src/components/input/input.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
describe,
23
it,
34
expect,
45
beforeEach,
@@ -215,9 +216,48 @@ export function main() {
215216
})();
216217
});
217218
}));
219+
220+
it('supports number types and conserved its value type from Angular', injectAsync([], () => {
221+
return builder.createAsync(MdInputNumberTypeConservedTestComponent)
222+
.then((fixture: ComponentFixture) => {
223+
fixture.detectChanges();
224+
225+
const inputEl = fixture.debugElement.query(By.css('input')).nativeElement;
226+
inputEl.value = '3';
227+
228+
// Manually trigger an onchange event.
229+
var evt = document.createEvent('HTMLEvents');
230+
evt.initEvent('change', true, true);
231+
inputEl.dispatchEvent(evt);
232+
233+
fixture.detectChanges();
234+
235+
// Something along the chain of events is asynchronous but does not use Zones, therefore
236+
// we need to wait for that something to propagate. Using fakeAsync fails, just returning
237+
// Promise.resolve(fixture) fails as well, but this passes.
238+
return new Promise((resolve) => {
239+
window.setTimeout(() => resolve(fixture), 0);
240+
});
241+
}).then((fixture: any) => {
242+
expect(fixture.componentInstance.value).toBe(3);
243+
expect(typeof fixture.componentInstance.value).toBe('number');
244+
});
245+
}));
218246
});
219247
}
220248

249+
@Component({
250+
selector: 'test-input-controller',
251+
template: `
252+
<md-input type="number" [(ngModel)]="value">
253+
</md-input>
254+
`,
255+
directives: [MD_INPUT_DIRECTIVES]
256+
})
257+
class MdInputNumberTypeConservedTestComponent {
258+
value: number = 0;
259+
}
260+
221261
@Component({
222262
selector: 'test-input-controller',
223263
template: `

src/components/input/input.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
143143

144144
get value(): any { return this._value; };
145145
@Input() set value(v: any) {
146+
v = this._convertValueForInputType(v);
146147
if (v !== this._value) {
147148
this._value = v;
148149
this._onChangeCallback(v);
@@ -163,6 +164,11 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
163164
this._focused = false;
164165
this._onTouchedCallback();
165166
}
167+
/** @internal */
168+
onChange(ev: Event) {
169+
this.value = (<HTMLInputElement>ev.target).value;
170+
this._onTouchedCallback();
171+
}
166172

167173
/** @internal */
168174
hasPlaceholder(): boolean {
@@ -197,6 +203,19 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
197203
this._validateConstraints();
198204
}
199205

206+
/**
207+
* Convert the value passed in to a value that is expected from the type of the md-input.
208+
* This is normally performed by the *_VALUE_ACCESSOR in forms, but since the type is bound
209+
* on our internal input it won't work locally.
210+
* @private
211+
*/
212+
private _convertValueForInputType(v: any): any {
213+
switch (this.type) {
214+
case 'number': return parseFloat(v);
215+
default: return v;
216+
}
217+
}
218+
200219
/**
201220
* Ensure that all constraints defined by the API are validated, or throw errors otherwise.
202221
* Constraints for now:

0 commit comments

Comments
 (0)