diff --git a/templates/component.tst b/templates/component.tst index 08a6bdc44..bae3be26d 100644 --- a/templates/component.tst +++ b/templates/component.tst @@ -1,10 +1,10 @@ -<#? it.isEditor #>/* tslint:disable:directive-selector */<#?#> <# var collectionProperties = it.properties.filter(item => item.isCollection).map(item => item.name); #> <# var collectionNestedComponents = it.nestedComponents.filter(item => item.isCollection && item.root); #> <# var baseClass = it.isExtension ? 'DxComponentExtension' : 'DxComponent'; #> <# var implementedInterfaces = ['OnDestroy']; #> <# !it.isExtension && implementedInterfaces.push('AfterViewInit'); #> +<# it.isEditor && implementedInterfaces.push('ControlValueAccessor'); #> <# collectionProperties.length && implementedInterfaces.push('OnChanges', 'DoCheck'); #> import { @@ -17,7 +17,6 @@ import { OnDestroy<#? !it.isExtension #>, AfterViewInit<#?#><#? it.isEditor #>, ContentChild, - Directive, forwardRef, HostListener<#?#><#? collectionProperties.length #>, OnChanges, @@ -48,13 +47,22 @@ import { WatcherHelper } from '../core/watcher-helper'; <#~ collectionNestedComponents :component:i #>import { <#= component.className #>Component } from './nested/<#= component.path #>'; <#~#> +<#? it.isEditor #> + +const CUSTOM_VALUE_ACCESSOR_PROVIDER = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => <#= it.className #>Component), + multi: true +};<#?#> + @Component({ selector: '<#= it.selector #>', template: '<#? it.isTranscludedContent #><#?#>',<#? it.isViz #> styles: [ ' :host { display: block; }'],<#?#> providers: [ DxTemplateHost, - WatcherHelper, + WatcherHelper,<#? it.isEditor #> + CUSTOM_VALUE_ACCESSOR_PROVIDER,<#?#> NestedOptionHost<#? collectionProperties.length #>, IterableDifferHelper<#?#> ] @@ -63,8 +71,8 @@ export class <#= it.className #>Component extends <#= baseClass #> <#? implement instance: <#= it.className #>; <#? it.isEditor #> @ContentChild(DxValidatorComponent) - validator: DxValidatorComponent;<#?#> - + validator: DxValidatorComponent; +<#?#> <#~ it.properties :prop:i #>@Input() get <#= prop.name #>(): any { return this._getOption('<#= prop.name #>'); @@ -78,6 +86,10 @@ export class <#= it.className #>Component extends <#= baseClass #> <#? implement <#~ it.events :event:i #>@Output() <#= event.emit #>;<#? i < it.events.length-1 #> <#?#><#~#> +<#? it.isEditor #> + @HostListener('valueChange', ['$event']) change(_) { } + touched = () => {};<#?#> + <#~ collectionNestedComponents :component:i #> @ContentChildren(<#= component.className #>Component) get <#= component.propertyName #>Children(): QueryList<<#= component.className #>Component> { @@ -110,7 +122,18 @@ export class <#= it.className #>Component extends <#= baseClass #> <#? implement } return widget;<#?#><#? !it.isEditor #>return new <#= it.className #>(element, options);<#?#> } - +<#? it.isEditor #> + writeValue(value: any): void { + this.value = value; + } +<#? it.widgetName !== "dxRangeSelector" #> + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + } +<#?#> + registerOnChange(fn: (_: any) => void): void { this.change = fn; } + registerOnTouched(fn: () => void): void { this.touched = fn; } +<#?#> ngOnDestroy() { this._destroyWidget(); } @@ -129,50 +152,17 @@ export class <#= it.className #>Component extends <#= baseClass #> <#? implement }<#?#> } -<#? it.isEditor #> - -const CUSTOM_VALUE_ACCESSOR = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => <#= it.className #>ValueAccessorDirective), - multi: true -}; - -@Directive({ - selector: '<#= it.selector #>[formControlName],<#= it.selector #>[formControl],<#= it.selector #>[ngModel]', - providers: [CUSTOM_VALUE_ACCESSOR] -}) -export class <#= it.className #>ValueAccessorDirective implements ControlValueAccessor { - @HostListener('valueChange', ['$event']) onChange(_) { } - onTouched = () => {}; - - constructor(private host: <#= it.className #>Component) { } - - writeValue(value: any): void { - this.host.value = value; - } -<#? it.widgetName !== "dxRangeSelector" #> - setDisabledState(isDisabled: boolean): void { - this.host.disabled = isDisabled; - }<#?#> - - registerOnChange(fn: (_: any) => void): void { this.onChange = fn; } - registerOnTouched(fn: () => void): void { this.onTouched = fn; } -} -<#?#> - @NgModule({ imports: [<#~ it.nestedComponents :component:i #> <#= component.className #>Module,<#~#> DxTemplateModule ], declarations: [ - <#= it.className #>Component<#? it.isEditor #>, - <#= it.className #>ValueAccessorDirective<#?#> + <#= it.className #>Component ], exports: [ <#= it.className #>Component<#~ it.nestedComponents :component:i #>, - <#= component.className #>Module<#~#>,<#? it.isEditor #> - <#= it.className #>ValueAccessorDirective,<#?#> + <#= component.className #>Module<#~#>, DxTemplateModule ], }) diff --git a/tests/src/ui/custom-value-accessor-implementation.spec.ts b/tests/src/ui/custom-value-accessor-implementation.spec.ts index bbbf67f15..a8e8c649d 100644 --- a/tests/src/ui/custom-value-accessor-implementation.spec.ts +++ b/tests/src/ui/custom-value-accessor-implementation.spec.ts @@ -28,13 +28,14 @@ import { template: `
- +
` }) class TestContainerComponent implements OnInit { form: FormGroup; + value = ''; formControl: AbstractControl; ngOnInit() { @@ -77,4 +78,15 @@ describe('DxTextBox value accessor', () => { expect(instance.option('disabled')).toBe(false); })); + it('should change the value', async(() => { + let fixture = TestBed.createComponent(TestContainerComponent); + fixture.detectChanges(); + + let instance = getWidget(fixture); + + fixture.componentInstance.value = 'text'; + fixture.detectChanges(); + + expect(instance.option('value')).toBe('text'); + })); });