docs(forms): update API reference for value accessors (#26946)
PR Close #26946
This commit is contained in:
parent
e5c9f7a507
commit
99c5db1fb1
|
@ -17,17 +17,26 @@ export const CHECKBOX_VALUE_ACCESSOR: any = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The accessor for writing a value and listening to changes on a checkbox input element.
|
* @description
|
||||||
|
* A `ControlValueAccessor` for writing a value and listening to changes on a checkbox input
|
||||||
|
* element.
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* ### Example
|
|
||||||
*
|
*
|
||||||
* ```
|
* ### Using a checkbox with a reactive form.
|
||||||
* <input type="checkbox" name="rememberLogin" ngModel>
|
*
|
||||||
|
* The following example shows how to use a checkbox with a reactive form.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const rememberLoginControl = new FormControl();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <input type="checkbox" [formControl]="rememberLoginControl">
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
|
@ -37,17 +46,50 @@ export const CHECKBOX_VALUE_ACCESSOR: any = {
|
||||||
providers: [CHECKBOX_VALUE_ACCESSOR]
|
providers: [CHECKBOX_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a change event occurs on the input element.
|
||||||
|
*/
|
||||||
onChange = (_: any) => {};
|
onChange = (_: any) => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a blur event occurs on the input element.
|
||||||
|
*/
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "checked" property on the input element.
|
||||||
|
*
|
||||||
|
* @param value The checked value
|
||||||
|
*/
|
||||||
writeValue(value: any): void {
|
writeValue(value: any): void {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'checked', value);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'checked', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control value changes.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; }
|
registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control is touched.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
|
registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "disabled" property on the input element.
|
||||||
|
*
|
||||||
|
* @param isDisabled The disabled value
|
||||||
|
*/
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,18 +32,28 @@ function _isAndroid(): boolean {
|
||||||
export const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>('CompositionEventMode');
|
export const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>('CompositionEventMode');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default accessor for writing a value and listening to changes that is used by the
|
* @description
|
||||||
* `NgModel`, `FormControlDirective`, and `FormControlName` directives.
|
* The default `ControlValueAccessor` for writing a value and listening to changes on input
|
||||||
|
* elements. The accessor is used by the `FormControlDirective`, `FormControlName`, and
|
||||||
|
* `NgModel` directives.
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* ### Example
|
|
||||||
*
|
*
|
||||||
* ```
|
* ### Using the default value accessor
|
||||||
* <input type="text" name="searchQuery" ngModel>
|
*
|
||||||
|
* The following example shows how to use an input element that activates the default value accessor
|
||||||
|
* (in this case, a text field).
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const firstNameControl = new FormControl();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <input type="text" [formControl]="firstNameControl">
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
|
@ -61,7 +71,16 @@ export const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>('CompositionE
|
||||||
providers: [DEFAULT_VALUE_ACCESSOR]
|
providers: [DEFAULT_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class DefaultValueAccessor implements ControlValueAccessor {
|
export class DefaultValueAccessor implements ControlValueAccessor {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when an input event occurs on the input element.
|
||||||
|
*/
|
||||||
onChange = (_: any) => {};
|
onChange = (_: any) => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a blur event occurs on the input element.
|
||||||
|
*/
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
/** Whether the user is creating a composition string (IME events). */
|
/** Whether the user is creating a composition string (IME events). */
|
||||||
|
@ -75,14 +94,37 @@ export class DefaultValueAccessor implements ControlValueAccessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "value" property on the input element.
|
||||||
|
*
|
||||||
|
* @param value The checked value
|
||||||
|
*/
|
||||||
writeValue(value: any): void {
|
writeValue(value: any): void {
|
||||||
const normalizedValue = value == null ? '' : value;
|
const normalizedValue = value == null ? '' : value;
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'value', normalizedValue);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'value', normalizedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control value changes.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
|
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control is touched.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
|
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "disabled" property on the input element.
|
||||||
|
*
|
||||||
|
* @param isDisabled The disabled value
|
||||||
|
*/
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,27 @@ export const NUMBER_VALUE_ACCESSOR: any = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The accessor for writing a number value and listening to changes that is used by the
|
* @description
|
||||||
* `NgModel`, `FormControlDirective`, and `FormControlName` directives.
|
* The `ControlValueAccessor` for writing a number value and listening to number input changes.
|
||||||
|
* The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`
|
||||||
|
* directives.
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* ### Example
|
|
||||||
*
|
*
|
||||||
* ```
|
* ### Using a number input with a reactive form.
|
||||||
* <input type="number" [(ngModel)]="age">
|
*
|
||||||
|
* The following example shows how to use a number input with a reactive form.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const totalCountControl = new FormControl();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <input type="number" [formControl]="totalCountControl">
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
*/
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector:
|
selector:
|
||||||
|
@ -41,22 +50,55 @@ export const NUMBER_VALUE_ACCESSOR: any = {
|
||||||
providers: [NUMBER_VALUE_ACCESSOR]
|
providers: [NUMBER_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class NumberValueAccessor implements ControlValueAccessor {
|
export class NumberValueAccessor implements ControlValueAccessor {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a change or input event occurs on the input
|
||||||
|
* element.
|
||||||
|
*/
|
||||||
onChange = (_: any) => {};
|
onChange = (_: any) => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a blur event occurs on the input element.
|
||||||
|
*/
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "value" property on the input element.
|
||||||
|
*
|
||||||
|
* @param value The checked value
|
||||||
|
*/
|
||||||
writeValue(value: number): void {
|
writeValue(value: number): void {
|
||||||
// The value needs to be normalized for IE9, otherwise it is set to 'null' when null
|
// The value needs to be normalized for IE9, otherwise it is set to 'null' when null
|
||||||
const normalizedValue = value == null ? '' : value;
|
const normalizedValue = value == null ? '' : value;
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'value', normalizedValue);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'value', normalizedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control value changes.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnChange(fn: (_: number|null) => void): void {
|
registerOnChange(fn: (_: number|null) => void): void {
|
||||||
this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); };
|
this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control is touched.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
|
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "disabled" property on the input element.
|
||||||
|
*
|
||||||
|
* @param isDisabled The disabled value
|
||||||
|
*/
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,16 +18,25 @@ export const RADIO_VALUE_ACCESSOR: any = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal class used by Angular to uncheck radio buttons with the matching name.
|
* @description
|
||||||
|
* Class used by Angular to track radio buttons. For internal use only.
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RadioControlRegistry {
|
export class RadioControlRegistry {
|
||||||
private _accessors: any[] = [];
|
private _accessors: any[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Adds a control to the internal registry. For internal use only.
|
||||||
|
*/
|
||||||
add(control: NgControl, accessor: RadioControlValueAccessor) {
|
add(control: NgControl, accessor: RadioControlValueAccessor) {
|
||||||
this._accessors.push([control, accessor]);
|
this._accessors.push([control, accessor]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Removes a control from the internal registry. For internal use only.
|
||||||
|
*/
|
||||||
remove(accessor: RadioControlValueAccessor) {
|
remove(accessor: RadioControlValueAccessor) {
|
||||||
for (let i = this._accessors.length - 1; i >= 0; --i) {
|
for (let i = this._accessors.length - 1; i >= 0; --i) {
|
||||||
if (this._accessors[i][1] === accessor) {
|
if (this._accessors[i][1] === accessor) {
|
||||||
|
@ -37,6 +46,10 @@ export class RadioControlRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Selects a radio button. For internal use only.
|
||||||
|
*/
|
||||||
select(accessor: RadioControlValueAccessor) {
|
select(accessor: RadioControlValueAccessor) {
|
||||||
this._accessors.forEach((c) => {
|
this._accessors.forEach((c) => {
|
||||||
if (this._isSameGroup(c, accessor) && c[1] !== accessor) {
|
if (this._isSameGroup(c, accessor) && c[1] !== accessor) {
|
||||||
|
@ -56,32 +69,22 @@ export class RadioControlRegistry {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
*
|
* The `ControlValueAccessor` for writing radio control values and listening to radio control
|
||||||
* Writes radio control values and listens to radio control changes.
|
* changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and
|
||||||
*
|
* `NgModel` directives.
|
||||||
* Used by `NgModel`, `FormControlDirective`, and `FormControlName`
|
|
||||||
* to keep the view synced with the `FormControl` model.
|
|
||||||
*
|
|
||||||
* If you have imported the `FormsModule` or the `ReactiveFormsModule`, this
|
|
||||||
* value accessor will be active on any radio control that has a form directive. You do
|
|
||||||
* **not** need to add a special selector to activate it.
|
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* ### How to use radio buttons with form directives
|
|
||||||
*
|
*
|
||||||
* To use radio buttons in a template-driven form, you'll want to ensure that radio buttons
|
* ### Using radio buttons with reactive form directives
|
||||||
* in the same group have the same `name` attribute. Radio buttons with different `name`
|
|
||||||
* attributes do not affect each other.
|
|
||||||
*
|
*
|
||||||
* {@example forms/ts/radioButtons/radio_button_example.ts region='TemplateDriven'}
|
* The follow example shows how to use radio buttons in a reactive form. When using radio buttons in
|
||||||
*
|
* a reactive form, radio buttons in the same group should have the same `formControlName`.
|
||||||
* When using radio buttons in a reactive form, radio buttons in the same group should have the
|
* Providing a `name` attribute is optional.
|
||||||
* same `formControlName`. You can also add a `name` attribute, but it's optional.
|
|
||||||
*
|
*
|
||||||
* {@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'}
|
* {@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'}
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
|
@ -101,32 +104,81 @@ export class RadioControlValueAccessor implements ControlValueAccessor,
|
||||||
/** @internal */
|
/** @internal */
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
_fn !: Function;
|
_fn !: Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a change event occurs on the input element.
|
||||||
|
*/
|
||||||
onChange = () => {};
|
onChange = () => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a blur event occurs on the input element.
|
||||||
|
*/
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the name of the radio input element.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input() name !: string;
|
@Input() name !: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the name of the `FormControl` bound to the directive. The name corresponds
|
||||||
|
* to a key in the parent `FormGroup` or `FormArray`.
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
@Input() formControlName !: string;
|
@Input() formControlName !: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the value of the radio input element
|
||||||
|
*/
|
||||||
@Input() value: any;
|
@Input() value: any;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _renderer: Renderer2, private _elementRef: ElementRef,
|
private _renderer: Renderer2, private _elementRef: ElementRef,
|
||||||
private _registry: RadioControlRegistry, private _injector: Injector) {}
|
private _registry: RadioControlRegistry, private _injector: Injector) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* A lifecycle method called when the directive is initialized. For internal use only.
|
||||||
|
*
|
||||||
|
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||||
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this._control = this._injector.get(NgControl);
|
this._control = this._injector.get(NgControl);
|
||||||
this._checkName();
|
this._checkName();
|
||||||
this._registry.add(this._control, this);
|
this._registry.add(this._control, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||||
|
*
|
||||||
|
* @param changes A object of key/value pairs for the set of changed inputs.
|
||||||
|
*/
|
||||||
ngOnDestroy(): void { this._registry.remove(this); }
|
ngOnDestroy(): void { this._registry.remove(this); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Sets the "checked" property value on the radio input element.
|
||||||
|
*
|
||||||
|
* @param value The checked value
|
||||||
|
*/
|
||||||
writeValue(value: any): void {
|
writeValue(value: any): void {
|
||||||
this._state = value === this.value;
|
this._state = value === this.value;
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'checked', this._state);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'checked', this._state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control value changes.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnChange(fn: (_: any) => {}): void {
|
registerOnChange(fn: (_: any) => {}): void {
|
||||||
this._fn = fn;
|
this._fn = fn;
|
||||||
this.onChange = () => {
|
this.onChange = () => {
|
||||||
|
@ -135,10 +187,26 @@ export class RadioControlValueAccessor implements ControlValueAccessor,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "value" on the radio input element and unchecks it.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
fireUncheck(value: any): void { this.writeValue(value); }
|
fireUncheck(value: any): void { this.writeValue(value); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control is touched.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
|
registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "disabled" property on the input element.
|
||||||
|
*
|
||||||
|
* @param isDisabled The disabled value
|
||||||
|
*/
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,27 @@ export const RANGE_VALUE_ACCESSOR: StaticProvider = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The accessor for writing a range value and listening to changes that is used by the
|
* @description
|
||||||
* `NgModel`, `FormControlDirective`, and `FormControlName` directives.
|
* The `ControlValueAccessor` for writing a range value and listening to range input changes.
|
||||||
|
* The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`
|
||||||
|
* directives.
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* ### Example
|
|
||||||
*
|
*
|
||||||
* ```
|
* ### Using a range input with a reactive form
|
||||||
* <input type="range" [(ngModel)]="age" >
|
*
|
||||||
|
* The following example shows how to use a range input with a reactive form.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* const ageControl = new FormControl();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <input type="range" [formControl]="ageControl">
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
*/
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector:
|
selector:
|
||||||
|
@ -41,21 +50,53 @@ export const RANGE_VALUE_ACCESSOR: StaticProvider = {
|
||||||
providers: [RANGE_VALUE_ACCESSOR]
|
providers: [RANGE_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class RangeValueAccessor implements ControlValueAccessor {
|
export class RangeValueAccessor implements ControlValueAccessor {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a change or input event occurs on the input
|
||||||
|
* element.
|
||||||
|
*/
|
||||||
onChange = (_: any) => {};
|
onChange = (_: any) => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a blur event occurs on the input element.
|
||||||
|
*/
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "value" property on the input element.
|
||||||
|
*
|
||||||
|
* @param value The checked value
|
||||||
|
*/
|
||||||
writeValue(value: any): void {
|
writeValue(value: any): void {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'value', parseFloat(value));
|
this._renderer.setProperty(this._elementRef.nativeElement, 'value', parseFloat(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control value changes.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnChange(fn: (_: number|null) => void): void {
|
registerOnChange(fn: (_: number|null) => void): void {
|
||||||
this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); };
|
this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control is touched.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
|
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "disabled" property on the range input element.
|
||||||
|
*
|
||||||
|
* @param isDisabled The disabled value
|
||||||
|
*/
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,35 +28,26 @@ function _extractId(valueString: string): string {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
*
|
* The `ControlValueAccessor` for writing select control values and listening to select control
|
||||||
* Writes values and listens to changes on a select element.
|
* changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and
|
||||||
*
|
* `NgModel` directives.
|
||||||
* Used by `NgModel`, `FormControlDirective`, and `FormControlName`
|
|
||||||
* to keep the view synced with the `FormControl` model.
|
|
||||||
*
|
|
||||||
* If you have imported the `FormsModule` or the `ReactiveFormsModule`, this
|
|
||||||
* value accessor will be active on any select control that has a form directive. You do
|
|
||||||
* **not** need to add a special selector to activate it.
|
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* ### How to use select controls with form directives
|
*
|
||||||
|
* ### Using select controls in a reactive form
|
||||||
|
*
|
||||||
|
* The following examples show how to use a select control in a reactive form.
|
||||||
|
*
|
||||||
|
* {@example forms/ts/reactiveSelectControl/reactive_select_control_example.ts region='Component'}
|
||||||
|
*
|
||||||
|
* ### Using select controls in a template-driven form
|
||||||
*
|
*
|
||||||
* To use a select in a template-driven form, simply add an `ngModel` and a `name`
|
* To use a select in a template-driven form, simply add an `ngModel` and a `name`
|
||||||
* attribute to the main `<select>` tag.
|
* attribute to the main `<select>` tag.
|
||||||
*
|
*
|
||||||
* If your option values are simple strings, you can bind to the normal `value` property
|
|
||||||
* on the option. If your option values happen to be objects (and you'd like to save the
|
|
||||||
* selection in your form as an object), use `ngValue` instead:
|
|
||||||
*
|
|
||||||
* {@example forms/ts/selectControl/select_control_example.ts region='Component'}
|
* {@example forms/ts/selectControl/select_control_example.ts region='Component'}
|
||||||
*
|
*
|
||||||
* In reactive forms, you'll also want to add your form directive (`formControlName` or
|
* ### Customizing option selection
|
||||||
* `formControl`) on the main `<select>` tag. Like in the former example, you have the
|
|
||||||
* choice of binding to the `value` or `ngValue` property on the select's options.
|
|
||||||
*
|
|
||||||
* {@example forms/ts/reactiveSelectControl/reactive_select_control_example.ts region='Component'}
|
|
||||||
*
|
|
||||||
* ### Caveat: Option selection
|
|
||||||
*
|
*
|
||||||
* Angular uses object identity to select option. It's possible for the identities of items
|
* Angular uses object identity to select option. It's possible for the identities of items
|
||||||
* to change while the data does not. This can happen, for example, if the items are produced
|
* to change while the data does not. This can happen, for example, if the items are produced
|
||||||
|
@ -67,10 +58,12 @@ function _extractId(valueString: string): string {
|
||||||
* `compareWith` takes a **function** which has two arguments: `option1` and `option2`.
|
* `compareWith` takes a **function** which has two arguments: `option1` and `option2`.
|
||||||
* If `compareWith` is given, Angular selects option by the return value of the function.
|
* If `compareWith` is given, Angular selects option by the return value of the function.
|
||||||
*
|
*
|
||||||
* ### Syntax
|
* ```ts
|
||||||
|
* const selectedCountriesControl = new FormControl();
|
||||||
|
* ```
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* <select [compareWith]="compareFn" [(ngModel)]="selectedCountries">
|
* <select [compareWith]="compareFn" [formControl]="selectedCountriesControl">
|
||||||
* <option *ngFor="let country of countries" [ngValue]="country">
|
* <option *ngFor="let country of countries" [ngValue]="country">
|
||||||
* {{country.name}}
|
* {{country.name}}
|
||||||
* </option>
|
* </option>
|
||||||
|
@ -81,13 +74,13 @@ function _extractId(valueString: string): string {
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Note: We listen to the 'change' event because 'input' events aren't fired
|
* **Note:** We listen to the 'change' event because 'input' events aren't fired
|
||||||
* for selects in Firefox and IE:
|
* for selects in Firefox and IE:
|
||||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1024350
|
* https://bugzilla.mozilla.org/show_bug.cgi?id=1024350
|
||||||
* https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/4660045/
|
* https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/4660045/
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
|
@ -103,9 +96,23 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_idCounter: number = 0;
|
_idCounter: number = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a change event occurs on the input element.
|
||||||
|
*/
|
||||||
onChange = (_: any) => {};
|
onChange = (_: any) => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a blur event occurs on the input element.
|
||||||
|
*/
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the option comparison algorithm for tracking identities when
|
||||||
|
* checking for changes.
|
||||||
|
*/
|
||||||
@Input()
|
@Input()
|
||||||
set compareWith(fn: (o1: any, o2: any) => boolean) {
|
set compareWith(fn: (o1: any, o2: any) => boolean) {
|
||||||
if (typeof fn !== 'function') {
|
if (typeof fn !== 'function') {
|
||||||
|
@ -118,6 +125,12 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||||
|
|
||||||
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "value" property on the input element. The "selectedIndex"
|
||||||
|
* property is also set if an ID is provided on the option element.
|
||||||
|
*
|
||||||
|
* @param value The checked value
|
||||||
|
*/
|
||||||
writeValue(value: any): void {
|
writeValue(value: any): void {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
const id: string|null = this._getOptionId(value);
|
const id: string|null = this._getOptionId(value);
|
||||||
|
@ -128,14 +141,32 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'value', valueString);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'value', valueString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control value changes.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnChange(fn: (value: any) => any): void {
|
registerOnChange(fn: (value: any) => any): void {
|
||||||
this.onChange = (valueString: string) => {
|
this.onChange = (valueString: string) => {
|
||||||
this.value = this._getOptionValue(valueString);
|
this.value = this._getOptionValue(valueString);
|
||||||
fn(this.value);
|
fn(this.value);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control is touched.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnTouched(fn: () => any): void { this.onTouched = fn; }
|
registerOnTouched(fn: () => any): void { this.onTouched = fn; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "disabled" property on the select input element.
|
||||||
|
*
|
||||||
|
* @param isDisabled The disabled value
|
||||||
|
*/
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||||
}
|
}
|
||||||
|
@ -160,17 +191,20 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
*
|
|
||||||
* Marks `<option>` as dynamic, so Angular can be notified when options change.
|
* Marks `<option>` as dynamic, so Angular can be notified when options change.
|
||||||
*
|
*
|
||||||
* See docs for `SelectControlValueAccessor` for usage examples.
|
* @see `SelectControlValueAccessor`
|
||||||
*
|
*
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
@Directive({selector: 'option'})
|
@Directive({selector: 'option'})
|
||||||
export class NgSelectOption implements OnDestroy {
|
export class NgSelectOption implements OnDestroy {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* ID of the option element
|
||||||
|
*/
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
id !: string;
|
id !: string;
|
||||||
|
|
||||||
|
@ -180,6 +214,11 @@ export class NgSelectOption implements OnDestroy {
|
||||||
if (this._select) this.id = this._select._registerOption();
|
if (this._select) this.id = this._select._registerOption();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the value bound to the option element. Unlike the value binding,
|
||||||
|
* ngValue supports binding to objects.
|
||||||
|
*/
|
||||||
@Input('ngValue')
|
@Input('ngValue')
|
||||||
set ngValue(value: any) {
|
set ngValue(value: any) {
|
||||||
if (this._select == null) return;
|
if (this._select == null) return;
|
||||||
|
@ -188,6 +227,11 @@ export class NgSelectOption implements OnDestroy {
|
||||||
this._select.writeValue(this._select.value);
|
this._select.writeValue(this._select.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks simple string values bound to the option element.
|
||||||
|
* For objects, use the `ngValue` input binding.
|
||||||
|
*/
|
||||||
@Input('value')
|
@Input('value')
|
||||||
set value(value: any) {
|
set value(value: any) {
|
||||||
this._setElementValue(value);
|
this._setElementValue(value);
|
||||||
|
@ -199,6 +243,10 @@ export class NgSelectOption implements OnDestroy {
|
||||||
this._renderer.setProperty(this._element.nativeElement, 'value', value);
|
this._renderer.setProperty(this._element.nativeElement, 'value', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||||
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this._select) {
|
if (this._select) {
|
||||||
this._select._optionMap.delete(this.id);
|
this._select._optionMap.delete(this.id);
|
||||||
|
|
|
@ -41,34 +41,36 @@ abstract class HTMLCollection {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The accessor for writing a value and listening to changes on a select element.
|
* @description
|
||||||
|
* The `ControlValueAccessor` for writing multi-select control values and listening to multi-select control
|
||||||
|
* changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`
|
||||||
|
* directives.
|
||||||
|
*
|
||||||
|
* @see `SelectControlValueAccessor`
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @usageNotes
|
||||||
* ### Caveat: Options selection
|
|
||||||
*
|
*
|
||||||
* Angular uses object identity to select options. It's possible for the identities of items
|
* ### Using a multi-select control
|
||||||
* to change while the data does not. This can happen, for example, if the items are produced
|
|
||||||
* from an RPC to the server, and that RPC is re-run. Even if the data hasn't changed, the
|
|
||||||
* second response will produce objects with different identities.
|
|
||||||
*
|
*
|
||||||
* To customize the default option comparison algorithm, `<select multiple>` supports `compareWith`
|
* The follow example shows you how to use a multi-select control with a reactive form.
|
||||||
* input. `compareWith` takes a **function** which has two arguments: `option1` and `option2`.
|
|
||||||
* If `compareWith` is given, Angular selects options by the return value of the function.
|
|
||||||
*
|
*
|
||||||
* ### Syntax
|
* ```ts
|
||||||
|
* const countryControl = new FormControl();
|
||||||
|
* ```
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* <select multiple [compareWith]="compareFn" [(ngModel)]="selectedCountries">
|
* <select multiple name="countries" [formControl]="countryControl">
|
||||||
* <option *ngFor="let country of countries" [ngValue]="country">
|
* <option *ngFor="let country of countries" [ngValue]="country">
|
||||||
* {{country.name}}
|
* {{ country.name }}
|
||||||
* </option>
|
* </option>
|
||||||
* </select>
|
* </select>
|
||||||
*
|
|
||||||
* compareFn(c1: Country, c2: Country): boolean {
|
|
||||||
* return c1 && c2 ? c1.id === c2.id : c1 === c2;
|
|
||||||
* }
|
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
* ### Customizing option selection
|
||||||
|
*
|
||||||
|
* To customize the default option comparison algorithm, `<select>` supports `compareWith` input.
|
||||||
|
* See the `SelectControlValueAccessor` for usage.
|
||||||
|
*
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
* @ngModule FormsModule
|
* @ngModule FormsModule
|
||||||
* @publicApi
|
* @publicApi
|
||||||
|
@ -80,15 +82,34 @@ abstract class HTMLCollection {
|
||||||
providers: [SELECT_MULTIPLE_VALUE_ACCESSOR]
|
providers: [SELECT_MULTIPLE_VALUE_ACCESSOR]
|
||||||
})
|
})
|
||||||
export class SelectMultipleControlValueAccessor implements ControlValueAccessor {
|
export class SelectMultipleControlValueAccessor implements ControlValueAccessor {
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The current value
|
||||||
|
*/
|
||||||
value: any;
|
value: any;
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_optionMap: Map<string, NgSelectMultipleOption> = new Map<string, NgSelectMultipleOption>();
|
_optionMap: Map<string, NgSelectMultipleOption> = new Map<string, NgSelectMultipleOption>();
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_idCounter: number = 0;
|
_idCounter: number = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a change event occurs on the input element.
|
||||||
|
*/
|
||||||
onChange = (_: any) => {};
|
onChange = (_: any) => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* The registered callback function called when a blur event occurs on the input element.
|
||||||
|
*/
|
||||||
onTouched = () => {};
|
onTouched = () => {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the option comparison algorithm for tracking identities when
|
||||||
|
* checking for changes.
|
||||||
|
*/
|
||||||
@Input()
|
@Input()
|
||||||
set compareWith(fn: (o1: any, o2: any) => boolean) {
|
set compareWith(fn: (o1: any, o2: any) => boolean) {
|
||||||
if (typeof fn !== 'function') {
|
if (typeof fn !== 'function') {
|
||||||
|
@ -101,6 +122,13 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
|
||||||
|
|
||||||
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Sets the "value" property on one or of more
|
||||||
|
* of the select's options.
|
||||||
|
*
|
||||||
|
* @param value The value
|
||||||
|
*/
|
||||||
writeValue(value: any): void {
|
writeValue(value: any): void {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
let optionSelectedStateSetter: (opt: NgSelectMultipleOption, o: any) => void;
|
let optionSelectedStateSetter: (opt: NgSelectMultipleOption, o: any) => void;
|
||||||
|
@ -114,6 +142,13 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
|
||||||
this._optionMap.forEach(optionSelectedStateSetter);
|
this._optionMap.forEach(optionSelectedStateSetter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control value changes
|
||||||
|
* and writes an array of the selected options.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnChange(fn: (value: any) => any): void {
|
registerOnChange(fn: (value: any) => any): void {
|
||||||
this.onChange = (_: any) => {
|
this.onChange = (_: any) => {
|
||||||
const selected: Array<any> = [];
|
const selected: Array<any> = [];
|
||||||
|
@ -140,8 +175,20 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
|
||||||
fn(selected);
|
fn(selected);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Registers a function called when the control is touched.
|
||||||
|
*
|
||||||
|
* @param fn The callback function
|
||||||
|
*/
|
||||||
registerOnTouched(fn: () => any): void { this.onTouched = fn; }
|
registerOnTouched(fn: () => any): void { this.onTouched = fn; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the "disabled" property on the select input element.
|
||||||
|
*
|
||||||
|
* @param isDisabled The disabled value
|
||||||
|
*/
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
|
||||||
}
|
}
|
||||||
|
@ -169,18 +216,14 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @description
|
||||||
* Marks `<option>` as dynamic, so Angular can be notified when options change.
|
* Marks `<option>` as dynamic, so Angular can be notified when options change.
|
||||||
*
|
*
|
||||||
* @usageNotes
|
* @see `SelectMultipleControlValueAccessor`
|
||||||
* ### Example
|
|
||||||
*
|
*
|
||||||
* ```
|
|
||||||
* <select multiple name="city" ngModel>
|
|
||||||
* <option *ngFor="let c of cities" [value]="c"></option>
|
|
||||||
* </select>
|
|
||||||
* ```
|
|
||||||
* @ngModule FormsModule
|
|
||||||
* @ngModule ReactiveFormsModule
|
* @ngModule ReactiveFormsModule
|
||||||
|
* @ngModule FormsModule
|
||||||
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
@Directive({selector: 'option'})
|
@Directive({selector: 'option'})
|
||||||
export class NgSelectMultipleOption implements OnDestroy {
|
export class NgSelectMultipleOption implements OnDestroy {
|
||||||
|
@ -197,6 +240,11 @@ export class NgSelectMultipleOption implements OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks the value bound to the option element. Unlike the value binding,
|
||||||
|
* ngValue supports binding to objects.
|
||||||
|
*/
|
||||||
@Input('ngValue')
|
@Input('ngValue')
|
||||||
set ngValue(value: any) {
|
set ngValue(value: any) {
|
||||||
if (this._select == null) return;
|
if (this._select == null) return;
|
||||||
|
@ -205,6 +253,11 @@ export class NgSelectMultipleOption implements OnDestroy {
|
||||||
this._select.writeValue(this._select.value);
|
this._select.writeValue(this._select.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Tracks simple string values bound to the option element.
|
||||||
|
* For objects, use the `ngValue` input binding.
|
||||||
|
*/
|
||||||
@Input('value')
|
@Input('value')
|
||||||
set value(value: any) {
|
set value(value: any) {
|
||||||
if (this._select) {
|
if (this._select) {
|
||||||
|
@ -226,6 +279,10 @@ export class NgSelectMultipleOption implements OnDestroy {
|
||||||
this._renderer.setProperty(this._element.nativeElement, 'selected', selected);
|
this._renderer.setProperty(this._element.nativeElement, 'selected', selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* Lifecycle method called before the directive's instance is destroyed. For internal use only.
|
||||||
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this._select) {
|
if (this._select) {
|
||||||
this._select._optionMap.delete(this.id);
|
this._select._optionMap.delete(this.id);
|
||||||
|
|
Loading…
Reference in New Issue