X Tutup
Skip to content

Commit 56a9b02

Browse files
committed
fix(default_value_accessor): support custom input elements that fire custom change events.
Closes #4878
1 parent de6774c commit 56a9b02

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

modules/angular2/src/core/forms/directives/default_value_accessor.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ const DEFAULT_VALUE_ACCESSOR = CONST_EXPR(new Provider(
1919
* ```
2020
*/
2121
@Directive({
22-
selector: '[ng-control],[ng-model],[ng-form-control]',
22+
selector:
23+
'input:not([type=checkbox])[ng-control],textarea[ng-control],input:not([type=checkbox])[ng-form-control],textarea[ng-form-control],input:not([type=checkbox])[ng-model],textarea[ng-model]',
24+
// TODO: vsavkin replace the above selector with the one below it once
25+
// https://github.com/angular/angular/issues/3011 is implemented
26+
// selector: '[ng-control],[ng-model],[ng-form-control]',
2327
host: {
2428
'(change)': 'onChange($event.target.value)',
2529
'(input)': 'onChange($event.target.value)',

modules/angular2/test/core/forms/integration_spec.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, Directive, View} from 'angular2/angular2';
1+
import {Component, Directive, View, Output, EventEmitter} from 'angular2/angular2';
22
import {
33
RootTestComponent,
44
afterEach,
@@ -32,6 +32,7 @@ import {
3232
} from 'angular2/core';
3333
import {By} from 'angular2/src/core/debug';
3434
import {ListWrapper} from 'angular2/src/core/facade/collection';
35+
import {ObservableWrapper} from 'angular2/src/core/facade/async';
3536

3637
export function main() {
3738
describe("integration tests", () => {
@@ -366,6 +367,29 @@ export function main() {
366367
async.done();
367368
});
368369
}));
370+
371+
it("should support custom value accessors on non builtin input elements that fire a change event without a 'target' property",
372+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
373+
var t = `<div [ng-form-model]="form">
374+
<my-input ng-control="name"></my-input>
375+
</div>`;
376+
377+
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((rootTC) => {
378+
rootTC.debugElement.componentInstance.form =
379+
new ControlGroup({"name": new Control("aa")});
380+
rootTC.detectChanges();
381+
var input = rootTC.debugElement.query(By.css("my-input"));
382+
expect(input.componentInstance.value).toEqual("!aa!");
383+
384+
input.componentInstance.value = "!bb!";
385+
ObservableWrapper.subscribe(input.componentInstance.onChange, (value) => {
386+
expect(rootTC.debugElement.componentInstance.form.value).toEqual({"name": "bb"});
387+
async.done();
388+
});
389+
input.componentInstance.dispatchChangeEvent();
390+
});
391+
}));
392+
369393
});
370394

371395
describe("validations", () => {
@@ -872,8 +896,26 @@ class WrappedValue implements ControlValueAccessor {
872896
handleOnChange(value) { this.onChange(value.substring(1, value.length - 1)); }
873897
}
874898

899+
@Component({selector: "my-input", template: ''})
900+
class MyInput implements ControlValueAccessor {
901+
@Output('change') onChange: EventEmitter = new EventEmitter();
902+
value: string;
903+
904+
constructor(cd: NgControl) { cd.valueAccessor = this; }
905+
906+
writeValue(value) { this.value = `!${value}!`; }
907+
908+
registerOnChange(fn) { ObservableWrapper.subscribe(this.onChange, fn); }
909+
910+
registerOnTouched(fn) {}
911+
912+
dispatchChangeEvent() {
913+
ObservableWrapper.callNext(this.onChange, this.value.substring(1, this.value.length - 1));
914+
}
915+
}
916+
875917
@Component({selector: "my-comp"})
876-
@View({directives: [FORM_DIRECTIVES, WrappedValue, NgIf, NgFor]})
918+
@View({directives: [FORM_DIRECTIVES, WrappedValue, MyInput, NgIf, NgFor]})
877919
class MyComp {
878920
form: any;
879921
name: string;

0 commit comments

Comments
 (0)
X Tutup