Skip to content

Commit f6f5af3

Browse files
robertmesserlejelbourn
authored andcommitted
fix(input): adds blur and focus event support (#449)
closes #337
1 parent 358af3b commit f6f5af3

File tree

3 files changed

+63
-7
lines changed

3 files changed

+63
-7
lines changed

src/components/input/input.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
[spellcheck]="spellcheck"
1919
[attr.maxlength]="maxLength"
2020
[type]="type"
21-
(focus)="onFocus()"
22-
(blur)="onBlur()"
21+
(focus)="handleFocus($event)"
22+
(blur)="handleBlur($event)"
2323
[(ngModel)]="value"
24-
(change)="onChange($event)">
24+
(change)="handleChange($event)">
2525

2626
<label class="md-input-placeholder"
2727
[attr.for]="id"

src/components/input/input.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,30 @@ export function main() {
259259
expect(typeof fixture.componentInstance.value).toBe('number');
260260
});
261261
});
262+
263+
it('supports blur and focus events', () => {
264+
return builder.createAsync(MdInputWithBlurAndFocusEvents).then(fixture => {
265+
const testComponent = fixture.componentInstance;
266+
const inputComponent = fixture.debugElement.query(By.directive(MdInput)).componentInstance;
267+
const fakeEvent = <FocusEvent>{};
268+
fakeAsync(() => {
269+
spyOn(testComponent, 'onFocus');
270+
spyOn(testComponent, 'onBlur');
271+
272+
expect(testComponent.onFocus).not.toHaveBeenCalled();
273+
expect(testComponent.onBlur).not.toHaveBeenCalled();
274+
275+
inputComponent.handleFocus(fakeEvent);
276+
tick();
277+
expect(testComponent.onFocus).toHaveBeenCalledWith(fakeEvent);
278+
279+
280+
inputComponent.handleBlur(fakeEvent);
281+
tick();
282+
expect(testComponent.onBlur).toHaveBeenCalledWith(fakeEvent);
283+
})();
284+
});
285+
});
262286
});
263287
}
264288

@@ -407,3 +431,15 @@ class MdInputAriaTestController {
407431
ariaLabel: string = 'label';
408432
ariaDisabled: boolean = true;
409433
}
434+
435+
@Component({
436+
selector: 'test-input-controller',
437+
template: `
438+
<md-input (focus)="onFocus($event)" (blur)="onBlur($event)"></md-input>
439+
`,
440+
directives: [MdInput]
441+
})
442+
class MdInputWithBlurAndFocusEvents {
443+
onBlur(event: FocusEvent) {}
444+
onFocus(event: FocusEvent) {}
445+
}

src/components/input/input.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@ import {
1313
ElementRef,
1414
QueryList,
1515
OnChanges,
16+
EventEmitter,
17+
Output,
1618
} from '@angular/core';
1719
import {
1820
NG_VALUE_ACCESSOR,
1921
ControlValueAccessor
2022
} from '@angular/common';
2123
import {BooleanFieldValue} from '../../core/annotations/field-value';
2224
import {MdError} from '../../core/errors/error';
25+
import {Observable} from 'rxjs/Observable';
2326

2427

2528
const noop = () => {};
@@ -142,6 +145,19 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
142145
@Input() @BooleanFieldValue() spellcheck: boolean = false;
143146
@Input() type: string = 'text';
144147

148+
private _blurEmitter: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
149+
private _focusEmitter: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
150+
151+
@Output('blur')
152+
get onBlur(): Observable<FocusEvent> {
153+
return this._blurEmitter.asObservable();
154+
}
155+
156+
@Output('focus')
157+
get onFocus(): Observable<FocusEvent> {
158+
return this._focusEmitter.asObservable();
159+
}
160+
145161
get value(): any { return this._value; };
146162
@Input() set value(v: any) {
147163
v = this._convertValueForInputType(v);
@@ -165,17 +181,21 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
165181
}
166182

167183
/** @internal */
168-
onFocus() {
184+
handleFocus(event: FocusEvent) {
169185
this._focused = true;
186+
this._focusEmitter.emit(event);
170187
}
188+
171189
/** @internal */
172-
onBlur() {
190+
handleBlur(event: FocusEvent) {
173191
this._focused = false;
174192
this._onTouchedCallback();
193+
this._blurEmitter.emit(event);
175194
}
195+
176196
/** @internal */
177-
onChange(ev: Event) {
178-
this.value = (<HTMLInputElement>ev.target).value;
197+
handleChange(event: Event) {
198+
this.value = (<HTMLInputElement>event.target).value;
179199
this._onTouchedCallback();
180200
}
181201

0 commit comments

Comments
 (0)