UNPKG

di-controls

Version:
148 lines (147 loc) 5.59 kB
import { DIProxyControlGetValue, DIProxyControlSetValue } from 'di-controls/types'; import { DIControl, DIControlConfig } from './control'; import * as i0 from "@angular/core"; /** * Configuration for the `DIProxyControl`. */ export interface DIProxyControlConfig<TModel, TChildModel> extends DIControlConfig<TModel, TChildModel> { /** * Function that will be used to get value from the current object model and set it to the child control * when update is requested. */ getValue: DIProxyControlGetValue<TModel, TChildModel>; /** * Function that will be used to set value to the object model when child control value is changed. */ setValue: DIProxyControlSetValue<TModel, TChildModel>; } /** * `DIProxyControl` is very suitable. * It is typically used as a host and works exclusively with objects. It is * necessary to bind child controls to a specific property of the object, * thereby ensuring that they update only that specific property and not the * entire object as a whole. Please see `*DateRangePage`. * * ## Creating a control * To create a control you need to extend your `@Component` or `@Directive` from `DIProxyControl` class * and provide `getValue` and `setValue` functions that will be used to get and set value from the object * to the child control. * * ```ts fileName="custom-control.component.ts" * @Component({}) * export class CustomControlComponent extends DIProxyControl<MyObject> { * constructor() { * super({ * getValue: (model) => model.objectProperty, * setValue: (model, value) => ({...model, objectProperty: value}), * }); * } * } * ``` * * ## Registering as a host * By default your control can work only with `NgModel` and `FormControl`. But you can register your control as a host * for another controls, then your control will be able to update them and accept updates from them. To do that you need to * use `provideHostControl` function. * * ```ts {2} fileName="custom-control.component.ts" * @Component({ * providers: [provideHostControl(CustomControlComponent)], * }) * export class CustomControlComponent extends DIProxyControl<MyObject> { * constructor() { * super({ * getValue: (model) => model.objectProperty, * setValue: (model, value) => ({...model, objectProperty: value}), * }); * } * } * ``` * * ## Injecting host control * By default your control doesn't communicate with host controls. But you can inject host control and put it * into `super` call. This will register your control in the host control and start communication between them. * * > **Note** * > If you register your control as a host for another controls, then you can inject it * > only with `skipSelf` option. * * ```ts {5} fileName="custom-control.component.ts" * @Component({}) * export class CustomControlComponent extends DIProxyControl<MyObject> { * constructor() { * // we add `optional` option to make it possible to use this control without host * super({ * host: injectHostControl({optional: true}), * getValue: (model) => model.objectProperty, * setValue: (model, value) => ({...model, objectProperty: value}), * }); * } * } * ``` * * ## Getting model * To get model you need to use `model` property. It will return model for the current control. * * ```ts {9} fileName="custom-control.component.ts" * @Component({}) * export class CustomControlComponent extends DIProxyControl<MyObject> { * constructor() { * super( * getValue: (model) => model.objectProperty, * setValue: (model, value) => ({...model, objectProperty: value}), * ); * } * * @HostListener('click') * onClick() { * console.log(this.model()); * } * } * ``` * * ## Updating model * To update model you need to call `updateModel` method. It will update model for the current control and all * children controls, as well as for the `NgModel` or `FormControl`. * * ```ts {9} fileName="custom-control.component.ts" * @Component({}) * export class CustomControlComponent extends DIProxyControl<MyObject> { * constructor() { * super( * getValue: (model) => model.objectProperty, * setValue: (model, value) => ({...model, objectProperty: value}), * ); * } * * @HostListener('click') * onClick() { * this.updateModel({objectProperty: 'new value'}); * } * } * ``` * ## Catching updates * Sometimes you may need to catch updates from different sources. For example, to update the value of the native * input element. To do this, you can provide the `onIncomingUpdate` hook. * * ```ts {6} fileName="custom-control.component.ts" * @Component({}) * export class CustomControlComponent extends DIProxyControl<MyObject> { * constructor() { * super({ * onIncomingUpdate: (value: MyObject | null) => { * this.elementRef.nativeElement.value = value; * }, * }); * } * } * ``` */ export declare abstract class DIProxyControl<TModel, TChildModel> extends DIControl<TModel, TChildModel> { protected config: DIProxyControlConfig<TModel, TChildModel>; protected constructor(config: DIProxyControlConfig<TModel, TChildModel>); registerControl(control: DIControl<TChildModel>): void; protected updateControl(control: DIControl<TChildModel>, value: TModel | null): void; static ɵfac: i0.ɵɵFactoryDeclaration<DIProxyControl<any, any>, never>; static ɵdir: i0.ɵɵDirectiveDeclaration<DIProxyControl<any, any>, never, never, {}, {}, never, never, true, never>; }