File

src/modules/date-range-picker/components/date-range-picker.component.ts

Description

Component to display the stark date-range-picker

Extends

AbstractStarkUiComponent

Implements

ControlValueAccessor OnInit OnDestroy

Metadata

Index

Properties
Methods
Inputs
Outputs
Accessors

Constructor

Public constructor(logger: StarkLoggingService, injector: Injector, renderer: Renderer2, elementRef: ElementRef, cdRef: ChangeDetectorRef)

Class constructor

Parameters :
Name Type Optional Description
logger StarkLoggingService No
  • The StarkLoggingService instance of the application.
injector Injector No
  • The Injector of the application
renderer Renderer2 No
  • Angular Renderer2 wrapper for DOM manipulations.
elementRef ElementRef No
  • Reference to the DOM element where this component is attached to.
cdRef ChangeDetectorRef No
  • Reference to the change detector attached to this component

Inputs

dateFilter
Type : StarkDatePickerFilter

Filter function or a string Will be applied to both date-picker

dateMask
Type : StarkDatePickerMaskConfig | undefined

Timestamp Mask Configuration to apply on the start/end date-picker. If true is passed, the default mask config is applied: {DEFAULT_DATE_MASK_CONFIG|DEFAULT_DATE_MASK_CONFIG} If false is passed or if dateMask is not present, the directive is disabled. If a StarkTimestampMaskConfig is passed, it is set as the date mask config.

disabled
Type : boolean

Whether the date pickers are disabled

endDate
Type : Date | undefined

Source Date to be bound to the end datepicker model

endDateLabel
Type : string
Default value : "STARK.DATE_RANGE_PICKER.TO"

Label to be displayed in the end datepicker

endMaxDate
Type : moment.Moment | null

Maximum date of the end date picker

endMinDate
Type : moment.Moment | null

Minimum date of the end date picker

rangeFormGroup
Type : UntypedFormGroup

Input to manage both start date and end date.

rangePickerId
Type : string
Default value : ""

HTML "name" attribute of the element.

rangePickerName
Type : string
Default value : ""

HTML "name" attribute of the element.

required
Type : boolean

Whether the date pickers are required

startDate
Type : Date | undefined

Source Date to be bound to the start datepicker model

startDateLabel
Type : string
Default value : "STARK.DATE_RANGE_PICKER.FROM"

Label to be displayed in the end datepicker

startMaxDate
Type : moment.Moment | null

Maximum date of the start date picker

startMinDate
Type : moment.Moment | null

Minimum date of the start date picker

color
Type : string
Inherited from AbstractStarkUiComponent

Color theme

Outputs

dateRangeChanged
Type : EventEmitter

Output that will emit a specific date range whenever the selection has changed

Methods

Public ngOnDestroy
ngOnDestroy()

Angular lifecycle method

Returns : void
Public ngOnInit
ngOnInit()
Inherited from AbstractStarkUiComponent

Angular lifecycle method

Returns : void
Public onDateChanged
onDateChanged(dateOrigin: "start" | "end")

Handle the date changed on the start and end datepicker

Parameters :
Name Type Optional Description
dateOrigin "start" | "end" No
  • Whether the change was triggered by the start or end date picker
Returns : void

Properties

Private Optional _dateMask
Type : StarkDatePickerMaskConfig
Public endPicker
Type : StarkDatePickerComponent
Decorators :
@ViewChild('endPicker', {static: true})

Reference to the end datepicker embedded in this component

Public logger
Type : StarkLoggingService
Decorators :
@Inject(STARK_LOGGING_SERVICE)
- The `StarkLoggingService` instance of the application.
Static ngAcceptInputType_dateMask
Type : BooleanInput | StarkDatePickerMaskConfig
Static ngAcceptInputType_endMaxDate
Type : StarkDateInput
Static ngAcceptInputType_endMinDate
Type : StarkDateInput
Static ngAcceptInputType_required
Type : BooleanInput
Static ngAcceptInputType_startMaxDate
Type : StarkDateInput
Static ngAcceptInputType_startMinDate
Type : StarkDateInput
Public startPicker
Type : StarkDatePickerComponent
Decorators :
@ViewChild('startPicker', {static: true})

Reference to the start datepicker embedded in this component

Accessors

startDate
getstartDate()

Source Date to be bound to the start datepicker model

Returns : Date | undefined
setstartDate(value: Date | undefined)
Parameters :
Name Type Optional
value Date | undefined No
Returns : void
startDateFormControl
getstartDateFormControl()

The internal formControl used to manage the state of the starkDatePicker for the start date. This can be used to retrieve internal errors.

Example :

<stark-date-range-picker required #starkDateRangePicker > {{starkDateRangePicker.startDateFormControl.hasError('required') ? "Start date is required" : null }}

Example :
&lt;stark-date-range-picker required #starkDateRangePicker &gt;
  <ng-container start-date-errors>
    {{starkDateRangePicker.startDateFormControl.hasError(&#39;required&#39;) ? &quot;Start date is required&quot; : null }}
  </ng-container>
</stark-date-range-picker>
Returns : UntypedFormControl
startMinDate
getstartMinDate()
setstartMinDate(value: moment.Moment | null)

Minimum date of the start date picker

Parameters :
Name Type Optional
value moment.Moment | null No
Returns : void
startMaxDate
getstartMaxDate()
setstartMaxDate(value: moment.Moment | null)

Maximum date of the start date picker

Parameters :
Name Type Optional
value moment.Moment | null No
Returns : void
endDate
getendDate()

Source Date to be bound to the end datepicker model

Returns : Date | undefined
setendDate(value: Date | undefined)
Parameters :
Name Type Optional
value Date | undefined No
Returns : void
endDateFormControl
getendDateFormControl()

The internal formControl used to manage the state of the starkDatePicker for the start date. This can be used to retrieve internal errors.

Example :

<stark-date-range-picker required #starkDateRangePicker > {{starkDateRangePicker.endDateFormControl.hasError('required') ? "End date is required" : null }}

Example :
&lt;stark-date-range-picker required #starkDateRangePicker &gt;
  <ng-container end-date-errors>
    {{starkDateRangePicker.endDateFormControl.hasError(&#39;required&#39;) ? &quot;End date is required&quot; : null }}
  </ng-container>
</stark-date-range-picker>
Returns : UntypedFormControl
endMinDate
getendMinDate()
setendMinDate(value: moment.Moment | null)

Minimum date of the end date picker

Parameters :
Name Type Optional
value moment.Moment | null No
Returns : void
endMaxDate
getendMaxDate()
setendMaxDate(value: moment.Moment | null)

Maximum date of the end date picker

Parameters :
Name Type Optional
value moment.Moment | null No
Returns : void
rangeFormGroup
setrangeFormGroup(val: UntypedFormGroup)

Input to manage both start date and end date.

Parameters :
Name Type Optional
val UntypedFormGroup No
Returns : void
dateMask
getdateMask()

Timestamp Mask Configuration to apply on the start/end date-picker. If true is passed, the default mask config is applied: {DEFAULT_DATE_MASK_CONFIG|DEFAULT_DATE_MASK_CONFIG} If false is passed or if dateMask is not present, the directive is disabled. If a StarkTimestampMaskConfig is passed, it is set as the date mask config.

setdateMask(value: StarkDatePickerMaskConfig | undefined)
Parameters :
Name Type Optional
value StarkDatePickerMaskConfig | undefined No
Returns : void
disabled
setdisabled(val: boolean)

Whether the date pickers are disabled

Parameters :
Name Type Optional
val boolean No
Returns : void
required
getrequired()

Whether the date pickers are required

Returns : boolean
setrequired(value: boolean)
Parameters :
Name Type Optional
value boolean No
Returns : void
import {
	ChangeDetectorRef,
	Component,
	ElementRef,
	EventEmitter,
	Inject,
	Injector,
	Input,
	OnDestroy,
	OnInit,
	Output,
	Renderer2,
	ViewChild,
	ViewEncapsulation
} from "@angular/core";
import {
	AbstractControl,
	ControlValueAccessor,
	UntypedFormControl,
	UntypedFormGroup,
	NG_VALUE_ACCESSOR,
	NgControl,
	ValidatorFn,
	Validators
} from "@angular/forms";
import { Subscription } from "rxjs";
import { distinctUntilChanged } from "rxjs/operators";
import get from "lodash-es/get";
import isEqual from "lodash-es/isEqual";
import { STARK_LOGGING_SERVICE, StarkLoggingService } from "@nationalbankbelgium/stark-core";
import { AbstractStarkUiComponent } from "@nationalbankbelgium/stark-ui/src/internal-common";
import {
	StarkDateInput,
	StarkDatePickerComponent,
	StarkDatePickerFilter,
	StarkDatePickerMaskConfig
} from "@nationalbankbelgium/stark-ui/src/modules/date-picker";
import { StarkDateRangePickerEvent } from "./date-range-picker-event.intf";
import { BooleanInput, coerceBooleanProperty } from "@angular/cdk/coercion";
import { isStarkTimestampMaskConfig } from "@nationalbankbelgium/stark-ui/src/modules/input-mask-directives";
import moment from "moment";

/**
 * @ignore
 */
const componentName = "stark-date-range-picker";

/**
 * Component to display the stark date-range-picker
 */
@Component({
	selector: "stark-date-range-picker",
	templateUrl: "./date-range-picker.component.html",
	encapsulation: ViewEncapsulation.None,
	// We need to use host instead of @HostBinding: https://github.com/NationalBankBelgium/stark/issues/664
	host: {
		class: componentName
	},
	providers: [
		{
			provide: NG_VALUE_ACCESSOR,
			multi: true,
			useExisting: StarkDateRangePickerComponent
		}
	]
})
export class StarkDateRangePickerComponent extends AbstractStarkUiComponent implements ControlValueAccessor, OnInit, OnDestroy {
	/**
	 * Source Date to be bound to the start datepicker model
	 */
	@Input()
	public get startDate(): Date | undefined {
		return this._startDate.value || undefined;
	}

	public set startDate(value: Date | undefined) {
		this._startDate.setValue(value);
	}

	/**
	 * The internal formControl used to manage the state of the starkDatePicker for the start date.
	 * This can be used to retrieve internal errors.
	 *
	 * @example
	 *
	 * <stark-date-range-picker required #starkDateRangePicker >
	 *   <ng-container start-date-errors>
	 *     {{starkDateRangePicker.startDateFormControl.hasError('required') ? "Start date is required" : null }}
	 *   </ng-container>
	 * </stark-date-range-picker>
	 */
	public get startDateFormControl(): UntypedFormControl {
		return this._startDate;
	}

	/**
	 * @ignore
	 */
	private _startDate!: UntypedFormControl; // will be defined by '_setupFormControls()' called in the constructor

	/**
	 * Label to be displayed in the end datepicker
	 */
	@Input()
	public startDateLabel = "STARK.DATE_RANGE_PICKER.FROM";

	/**
	 * Minimum date of the start date picker
	 */
	@Input()
	public set startMinDate(value: moment.Moment | null) {
		if (value === undefined) {
			// eslint-disable-next-line no-null/no-null
			this._startMinDate = null;
		} else if (value instanceof Date) {
			this._startMinDate = moment(value);
		} else {
			this._startMinDate = value;
		}
	}

	public get startMinDate(): moment.Moment | null {
		return this._startMinDate;
	}

	// Information about input setter coercion https://angular.io/guide/template-typecheck#input-setter-coercion
	public static ngAcceptInputType_startMinDate: StarkDateInput;

	/**
	 * @ignore
	 * Angular expects a Moment or null value.
	 */
	// eslint-disable-next-line no-null/no-null
	private _startMinDate: moment.Moment | null = null;

	/**
	 * Maximum date of the start date picker
	 */
	@Input()
	public set startMaxDate(value: moment.Moment | null) {
		if (value === undefined) {
			// eslint-disable-next-line no-null/no-null
			this._startMaxDate = null;
		} else if (value instanceof Date) {
			this._startMaxDate = moment(value);
		} else {
			this._startMaxDate = value;
		}
	}

	public get startMaxDate(): moment.Moment | null {
		return this._startMaxDate;
	}

	// Information about input setter coercion https://angular.io/guide/template-typecheck#input-setter-coercion
	public static ngAcceptInputType_startMaxDate: StarkDateInput;

	/**
	 * @ignore
	 * Angular expects a Moment or null value.
	 */
	// eslint-disable-next-line no-null/no-null
	private _startMaxDate: moment.Moment | null = null;

	/**
	 * Source Date to be bound to the end datepicker model
	 */
	@Input()
	public get endDate(): Date | undefined {
		return this._endDate.value || undefined;
	}

	public set endDate(value: Date | undefined) {
		this._endDate.setValue(value);
	}

	/**
	 * The internal formControl used to manage the state of the starkDatePicker for the start date.
	 * This can be used to retrieve internal errors.
	 *
	 * @example
	 *
	 * <stark-date-range-picker required #starkDateRangePicker >
	 *   <ng-container end-date-errors>
	 *     {{starkDateRangePicker.endDateFormControl.hasError('required') ? "End date is required" : null }}
	 *   </ng-container>
	 * </stark-date-range-picker>
	 */
	public get endDateFormControl(): UntypedFormControl {
		return this._endDate;
	}

	/**
	 * @ignore
	 */
	private _endDate!: UntypedFormControl; // will be defined by '_setupFormControls()' called in the constructor

	/**
	 * Label to be displayed in the end datepicker
	 */
	@Input()
	public endDateLabel = "STARK.DATE_RANGE_PICKER.TO";

	/**
	 * Minimum date of the end date picker
	 */
	@Input()
	public set endMinDate(value: moment.Moment | null) {
		if (value === undefined) {
			// eslint-disable-next-line no-null/no-null
			this._endMinDate = null;
		} else if (value instanceof Date) {
			this._endMinDate = moment(value);
		} else {
			this._endMinDate = value;
		}
	}

	public get endMinDate(): moment.Moment | null {
		// use the startDate when defined to provide better user experience :)
		return this.startDate ? moment(this.startDate) : this._endMinDate;
	}

	// Information about input setter coercion https://angular.io/guide/template-typecheck#input-setter-coercion
	public static ngAcceptInputType_endMinDate: StarkDateInput;

	/**
	 * @ignore
	 * Angular expects a Moment or null value.
	 */
	// eslint-disable-next-line no-null/no-null
	private _endMinDate: moment.Moment | null = null;

	/**
	 * Maximum date of the end date picker
	 */
	@Input()
	public set endMaxDate(value: moment.Moment | null) {
		if (value === undefined) {
			// eslint-disable-next-line no-null/no-null
			this._endMaxDate = null;
		} else if (value instanceof Date) {
			this._endMaxDate = moment(value);
		} else {
			this._endMaxDate = value;
		}
	}

	public get endMaxDate(): moment.Moment | null {
		return this._endMaxDate;
	}

	// Information about input setter coercion https://angular.io/guide/template-typecheck#input-setter-coercion
	public static ngAcceptInputType_endMaxDate: StarkDateInput;

	/**
	 * @ignore
	 * Angular expects a Moment or null value.
	 */
	// eslint-disable-next-line no-null/no-null
	private _endMaxDate: moment.Moment | null = null;

	/**
	 * Input to manage both start date and end date.
	 */
	@Input()
	public set rangeFormGroup(val: UntypedFormGroup) {
		const { startDate, endDate } = val.controls;
		if (!(startDate instanceof UntypedFormControl && endDate instanceof UntypedFormControl)) {
			this.logger.error(`[${componentName}]: "formGroup" requires a FormControl for startDate and another one for endDate`);
			return;
		}

		this._formGroup = val;
		// overwrite internal formControls and setup again the validators, subscriptions, etc.
		this._startDate = startDate;
		this._endDate = endDate;
		this._setupFormControls();
	}

	/**
	 * @ignore
	 */
	private _formGroup?: UntypedFormGroup;

	/**
	 * Filter function or a string
	 * Will be applied to both date-picker
	 */
	@Input()
	public dateFilter?: StarkDatePickerFilter;

	/**
	 * Timestamp Mask Configuration to apply on the start/end date-picker.
	 * If `true` is passed, the default mask config is applied: {DEFAULT_DATE_MASK_CONFIG|DEFAULT_DATE_MASK_CONFIG}
	 * If `false` is passed or if `dateMask` is not present, the directive is disabled.
	 * If a `StarkTimestampMaskConfig` is passed, it is set as the date mask config.
	 */
	@Input()
	public get dateMask(): StarkDatePickerMaskConfig | undefined {
		return this._dateMask;
	}

	public set dateMask(value: StarkDatePickerMaskConfig | undefined) {
		this._dateMask = isStarkTimestampMaskConfig(value) ? value : coerceBooleanProperty(value);
	}

	private _dateMask?: StarkDatePickerMaskConfig;

	// Information about boolean coercion https://angular.io/guide/template-typecheck#input-setter-coercion
	public static ngAcceptInputType_dateMask: BooleanInput | StarkDatePickerMaskConfig;

	/**
	 * Whether the date pickers are disabled
	 */
	@Input()
	public set disabled(val: boolean) {
		if (this._formGroup) {
			this.logger.warn(`[${componentName}]: 
			It looks like you're using the "disabled" attribute with a "formGroup". We recommend using following approach.
       
      Example: 
      dateRangeFormGroup = new FormGroup({
        startDate: new FormControl({value: null, disabled: true}),
        endDate: new FormControl({value: null, disabled: true})
      });
			`);
		}

		// enable/disable the controls without emitting a change event since the values did not change (to avoid unnecessary extra calls!)
		if (val) {
			if (this.startDateFormControl) {
				this.startDateFormControl.disable({ emitEvent: false });
			}
			if (this.endDateFormControl) {
				this.endDateFormControl.disable({ emitEvent: false });
			}
		} else {
			if (this.startDateFormControl) {
				this.startDateFormControl.enable({ emitEvent: false });
			}
			if (this.endDateFormControl) {
				this.endDateFormControl.enable({ emitEvent: false });
			}
		}
	}

	/**
	 * Whether the date pickers are required
	 */
	@Input()
	public get required(): boolean {
		return this._required;
	}

	public set required(value: boolean) {
		this._required = coerceBooleanProperty(value);
	}

	// Information about boolean coercion https://angular.io/guide/template-typecheck#input-setter-coercion
	public static ngAcceptInputType_required: BooleanInput;

	/**
	 * @ignore
	 * @internal
	 */
	private _required = false;

	/**
	 * HTML "name" attribute of the element.
	 */
	@Input()
	public rangePickerId = "";

	/**
	 * HTML "name" attribute of the element.
	 */
	@Input()
	public rangePickerName = "";

	/**
	 * Output that will emit a specific date range whenever the selection has changed
	 */
	@Output()
	public readonly dateRangeChanged = new EventEmitter<StarkDateRangePickerEvent>();

	/**
	 * Reference to the start datepicker embedded in this component
	 */
	@ViewChild("startPicker", { static: true })
	public startPicker!: StarkDatePickerComponent;

	/**
	 * Reference to the end datepicker embedded in this component
	 */
	@ViewChild("endPicker", { static: true })
	public endPicker!: StarkDatePickerComponent;

	/**
	 * @ignore
	 * @internal
	 * The registered callback function called when a blur event occurs on the input element.
	 */
	private _onTouched: () => void = () => {
		/* noop*/
	};

	/**
	 * @ignore
	 * @internal
	 * The registered callback function called when an input event occurs on the input element.
	 */
	private _onChange: (_dateRange: StarkDateRangePickerEvent) => void = (_: any) => {
		/* noop*/
	};

	/**
	 * Subscriptions to be removed at end of component lifecycle
	 * @ignore
	 */
	private subs: Subscription[] = [];

	/**
	 * @ignore
	 * @internal
	 */
	public currentRange?: StarkDateRangePickerEvent;

	/**
	 * @ignore
	 * @internal
	 */

	private _startBeforeEndValidator: ValidatorFn = ({ value }) =>
		value instanceof Date && this.endDate instanceof Date && value.getTime() > this.endDate.getTime() ? { startBeforeEnd: true } : null;

	/**
	 * @ignore
	 * @internal
	 */
	private _endAfterStartValidator: ValidatorFn = ({ value }) =>
		value instanceof Date && this.startDate instanceof Date && value.getTime() < this.startDate.getTime()
			? { endAfterStart: true }
			: null;

	/**
	 * @ignore
	 * @internal
	 * Validator that will perform the 'required' validation only if the 'required' input is enabled
	 * IMPORTANT: this should be always added to the internal form controls for the start and end date pickers
	 */
	private _requiredValidator: ValidatorFn = (control: AbstractControl) => {
		if (this.required) {
			return Validators.required(control);
		}

		return null;
	};

	/**
	 * Class constructor
	 * @param logger - The `StarkLoggingService` instance of the application.
	 * @param injector - The Injector of the application
	 * @param renderer - Angular `Renderer2` wrapper for DOM manipulations.
	 * @param elementRef - Reference to the DOM element where this component is attached to.
	 * @param cdRef - Reference to the change detector attached to this component
	 */
	public constructor(
		@Inject(STARK_LOGGING_SERVICE) public logger: StarkLoggingService,
		private injector: Injector,
		renderer: Renderer2,
		elementRef: ElementRef,
		protected cdRef: ChangeDetectorRef
	) {
		super(renderer, elementRef);
		// IMPORTANT: the form controls should be initialized here because they should be available before the developer passes his own form controls
		this._setupFormControls();
	}

	/**
	 * Angular lifecycle method
	 */
	public override ngOnInit(): void {
		super.ngOnInit();

		this._setupNgControl();
		this.logger.debug(componentName + ": component initialized");
	}

	/**
	 * Angular lifecycle method
	 */
	public ngOnDestroy(): void {
		for (const subscription of this.subs) {
			subscription.unsubscribe();
		}
	}

	/**
	 * @ignore
	 * @internal
	 */
	private _setupFormControls(): void {
		// merge the original validators with ones from the start/end date form controls if already available
		// or create the form controls with such validators otherwise
		// IMPORTANT: the '_requiredValidator' should ALWAYS be added. Internally it checks whether the control is actually required or not.
		// By doing this, the formControl will be marked as 'required' since the beginning (if it is marked as required).
		// This prevents the 'ExpressionChangedAfterItHasBeenCheckedError' in the template when the developer uses an NgModel and retrieves the internal errors
		// However, the error will NOT prevent the error from happening when FormControl is used (via the 'rangeFormGroup' input).
		if (this.startDateFormControl) {
			this.startDateFormControl.setValidators(
				Validators.compose([this.startDateFormControl.validator, this._requiredValidator, this._startBeforeEndValidator])
			);
		} else {
			this._startDate = new UntypedFormControl(undefined, [this._requiredValidator, this._startBeforeEndValidator]);
		}
		if (this.endDateFormControl) {
			this.endDateFormControl.setValidators(
				Validators.compose([this.endDateFormControl.validator, this._requiredValidator, this._endAfterStartValidator])
			);
		} else {
			this._endDate = new UntypedFormControl(undefined, [this._requiredValidator, this._endAfterStartValidator]);
		}

		for (const subscription of this.subs) {
			subscription.unsubscribe();
		}

		this.subs.push(
			this.startDateFormControl.valueChanges.pipe(distinctUntilChanged()).subscribe((_value: Date) => {
				this.onDateChanged("start");
			}),
			this.endDateFormControl.valueChanges.pipe(distinctUntilChanged()).subscribe((_value: Date) => {
				this.onDateChanged("end");
			})
		);
	}

	/**
	 * Link the passed control (if one is available) to the internal formControls.
	 * @ignore
	 * @internal
	 */
	private _setupNgControl(): void {
		// Get the ngControl from the injector
		const ngControl = this.injector.get<NgControl>(NgControl, <any>null);
		if (!ngControl) {
			return;
		}

		ngControl.valueAccessor = this;

		if (typeof get(ngControl, "control.validator") === "function") {
			this.logger.warn(
				`[${componentName}]: validators set on the control will not be used, use the "formGroup" attribute to manage your own validations.`
			);
		}
	}

	/**
	 * Handle the date changed on the start and end datepicker
	 * @param dateOrigin - Whether the change was triggered by the start or end date picker
	 */
	public onDateChanged(dateOrigin: "start" | "end"): void {
		this._onTouched();

		if (this.startDate && this.endDate && this.endDate.getTime() < this.startDate.getTime()) {
			// clear the value of one of the date pickers and make the change to affect ONLY that control
			// this is because at the end both controls will be validated once the final value is emitted (see the 'else' block below)
			if (dateOrigin === "start") {
				this.endDateFormControl.setValue(undefined, { onlySelf: true });
			} else {
				this.startDateFormControl.setValue(undefined, { onlySelf: true });
			}
			this.cdRef.detectChanges(); // to force a refresh of the validation errors
		} else {
			const dateRange: StarkDateRangePickerEvent = { startDate: this.startDate, endDate: this.endDate };

			if (!isEqual(dateRange, this.currentRange)) {
				// calling 'updateValueAndValidity()' manually on both form controls without emitting the valueChanges event (to avoid unnecessary extra calls in the end user's code!)
				this.startDateFormControl.updateValueAndValidity({ emitEvent: false });
				this.endDateFormControl.updateValueAndValidity({ emitEvent: false });

				this.currentRange = dateRange;
				this._onChange(dateRange);
				this.dateRangeChanged.emit(dateRange);
			}
		}
	}

	/**
	 * Part of {@link ControlValueAccessor} API
	 * Registers a function to be called when the control value changes.
	 * @ignore
	 * @internal
	 */
	public registerOnChange(fn: (_dateRange: StarkDateRangePickerEvent) => void): void {
		this._onChange = fn;
	}

	/**
	 * Part of {@link ControlValueAccessor} API
	 * Registers a function to be called when the control is touched.
	 * @ignore
	 * @internal
	 */
	public registerOnTouched(fn: () => void): void {
		this._onTouched = fn;
	}

	/**
	 * Part of {@link ControlValueAccessor} API
	 * Sets the "disabled" property on the input element.
	 * @ignore
	 * @internal
	 */
	public setDisabledState(isDisabled: boolean): void {
		this.disabled = isDisabled;
	}

	/**
	 * Part of {@link ControlValueAccessor} API
	 * Sets the "value" property on the input element.
	 * @ignore
	 * @internal
	 */
	public writeValue(dateRange: StarkDateRangePickerEvent): void {
		dateRange = dateRange || {};
		this.startDateFormControl.setValue(dateRange.startDate, { emitEvent: false });
		this.endDateFormControl.setValue(dateRange.endDate, { emitEvent: false });
	}
}
<mat-form-field>
	<stark-date-picker
		#startPicker
		[pickerId]="rangePickerId + '-start'"
		[pickerName]="rangePickerName + '-start'"
		[formControl]="startDateFormControl"
		[placeholder]="startDateLabel | translate"
		[dateFilter]="dateFilter"
		[dateMask]="dateMask"
		[min]="startMinDate"
		[max]="startMaxDate"
		[required]="required"
	>
	</stark-date-picker>
	<!-- <mat-error> should always be a direct child of <mat-form-field> -->
	<mat-error>
		<ng-content select="[start-date-errors]"></ng-content>
	</mat-error>
</mat-form-field>

<mat-form-field>
	<stark-date-picker
		#endPicker
		[pickerId]="rangePickerId + '-end'"
		[pickerName]="rangePickerName + '-end'"
		[formControl]="endDateFormControl"
		[placeholder]="endDateLabel | translate"
		[dateFilter]="dateFilter"
		[dateMask]="dateMask"
		[min]="endMinDate"
		[max]="endMaxDate"
		[required]="required"
	>
	</stark-date-picker>
	<!-- <mat-error> should always be a direct child of <mat-form-field> -->
	<mat-error>
		<ng-content select="[end-date-errors]"></ng-content>
	</mat-error>
</mat-form-field>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""