di-controls
Version:
<!-- PROJECT LOGO -->
148 lines (147 loc) • 5.59 kB
TypeScript
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>;
}