import { DICompareHost } from 'di-controls/classes';
import { DICompareFunction } from 'di-controls/types';
import { DIControl, DIControlConfig } from './control';
import * as i0 from "@angular/core";
/**
 * Configuration for the `DICollectionControl`.
 */
export interface DICollectionControlConfig<TModel, TChildModel> extends DIControlConfig<TModel[], TChildModel> {
    /**
     * Function that will be used to compare values in the array.
     * Useful when you want to compare objects by some property.
     */
    compare?: DICompareHost<TModel | null> | DICompareFunction<TModel | null> | null;
}
/**
 * `DICollectionControl` can be used to implement array controls (checkbox group, radio group, chips, etc.).
 * It has an additional integration with `DIStateControl` that allows you to use it as a host for
 * `DIStateControl` controls. If you use `DIStateControl` as a child control, then `DICollectionControl`
 * will update its model when the child control is checked or unchecked, so `DICollectionControl` will
 * contain only checked values.
 *
 * It also works with other controls, but their model should be an array.
 *
 * > **Warning**
 * > If child control model is updated with non-array value, then `DICollectionControl` will be updated with `null`.
 *
 * ## Creating a control
 * To create a control you need to extend your `@Component` or `@Directive` from `DICollectionControl` class.
 * After that your control will be able to work with `NgModel`, `FormControl`.
 *
 * ```ts fileName="custom-control.component.ts"
 * @Component({})
 * export class CustomControlComponent extends DICollectionControl<string> {
 *   constructor() {
 *    super();
 *  }
 * }
 *  ```
 *
 * ## 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 DICollectionControl<string> {
 *   constructor() {
 *     super();
 *   }
 * }
 * ```
 *
 * ## 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 DICollectionControl<string> {
 *   constructor() {
 *     // we add `optional` option to make it possible to use this control without host
 *     super({host: injectHostControl({optional: true})});
 *   }
 * }
 * ```
 *
 * ## 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 DICollectionControl<string> {
 *   constructor() {
 *     super();
 *   }
 *
 *   @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 DICollectionControl<string> {
 *   constructor() {
 *     super();
 *   }
 *
 *   @HostListener('click')
 *   onClick() {
 *     this.updateModel(['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 DICollectionControl<string> {
 *   constructor() {
 *     super({
 *       onIncomingUpdate: (value: string[] | null) => {
 *         this.elementRef.nativeElement.value = value;
 *       },
 *     });
 *   }
 * }
 * ```
 * ```
 */
export declare abstract class DICollectionControl<TModel> extends DIControl<TModel[], TModel | TModel[]> {
    protected config?: DICollectionControlConfig<TModel, TModel | TModel[]> | undefined;
    private proxyModel;
    protected constructor(config?: DICollectionControlConfig<TModel, TModel | TModel[]> | undefined);
    private getCompareFn;
    internalUpdateModel(obj: TModel[] | null): void;
    writeValue(value: TModel[] | null): void;
    writeValueFromHost(obj: TModel[] | null): void;
    protected childControlChange(control: DIControl<TModel | TModel[]>, value: TModel[] | null): void;
    private getNewModel;
    protected updateControl(control: DIControl<TModel | TModel[]>): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<DICollectionControl<any>, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<DICollectionControl<any>, never, never, {}, {}, never, never, true, never>;
}
