@progress/kendo-angular-label
Version:
Kendo UI Label for Angular
1,009 lines (993 loc) • 40 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import * as i0 from '@angular/core';
import { Directive, Input, HostBinding, EventEmitter, forwardRef, isDevMode, Component, Output, ContentChild, ViewChild, NgModule } from '@angular/core';
import { isDocumentAvailable, guid, hasObservers, KendoInput } from '@progress/kendo-angular-common';
import * as i1 from '@progress/kendo-angular-l10n';
import { ComponentMessages, LocalizationService, L10N_PREFIX } from '@progress/kendo-angular-l10n';
import { NgControl } from '@angular/forms';
import { validatePackage } from '@progress/kendo-licensing';
import { Observable, Subscription } from 'rxjs';
import { NgIf, NgClass, NgStyle } from '@angular/common';
/**
* @hidden
*/
const isInputElement = (component) => component instanceof HTMLElement;
/**
* @hidden
*/
const inputElementHasAttr = (element, attribute) => element.hasAttribute(attribute);
/**
* @hidden
*/
const getWrappedNativeInput = (element) => element.querySelector('kendo-label > input, kendo-label > textarea, kendo-label > select');
/**
* @hidden
*/
const getRootElement = (element) => {
if (!element) {
return null;
}
let rootElement = element;
while (rootElement.parentElement) {
rootElement = rootElement.parentElement;
}
return rootElement;
};
/**
* @hidden
*/
const nativeLabelForTargets = ['BUTTON', 'INPUT', 'METER', 'OUTPUT', 'PROGRESS', 'SELECT', 'TEXTAREA']; // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label
/**
* Represents the [Kendo UI Label directive for Angular]({% slug label_directive %}).
* Use the `LabelDirective` to link a focusable Angular component or HTML element to a `<label>` tag with the `[for]` property binding.
*
* To link a component with the `label` element:
* - Set the `[for]` property binding to a [template reference variable](link:site.data.urls.angular['templatesyntax']#template-reference-variables--var-), or
* - Set the `[for]` property binding to an `id` HTML string value.
*
* @example
* ```ts
* @Component({
* selector: 'my-app',
* template: `
* <div class="row example-wrapper" style="min-height: 450px;">
* <div class="col-xs-12 col-md-6 example-col">
* <label [for]="datepicker">DatePicker: </label>
* <kendo-datepicker #datepicker></kendo-datepicker>
* </div>
*
* <div class="col-xs-12 col-md-6 example-col">
* <label for="input">Input: </label>
* <input id="input" />
* </div>
* </div>
* `
* })
* class AppComponent { }
* ```
*/
class LabelDirective {
label;
renderer;
zone;
/**
* Sets the focusable target for the label.
* Accepts a [template reference variable](link:site.data.urls.angular['templatesyntax']#template-reference-variables--var-) or an `id` HTML string value.
*/
for;
get labelFor() {
if (typeof this.for === 'string') {
return this.for;
}
if (!isDocumentAvailable()) {
return null;
}
const component = this.getFocusableComponent() || {};
if (isInputElement(component) && !inputElementHasAttr(component, 'id')) {
this.renderer.setAttribute(component, 'id', `k-${guid()}`);
}
return component.focusableId || component.id || null;
}
/**
* @hidden
* Allows the user to specify if the label CSS class should be rendered or not.
*/
labelClass = true;
clickListener;
constructor(label, renderer, zone) {
this.label = label;
this.renderer = renderer;
this.zone = zone;
}
/**
* @hidden
*/
ngAfterViewInit() {
this.setAriaLabelledby();
this.zone.runOutsideAngular(() => this.clickListener = this.renderer.listen(this.label.nativeElement, 'click', this.handleClick));
}
/**
* @hidden
*/
ngOnDestroy() {
if (this.clickListener) {
this.clickListener();
}
}
/**
* @hidden
*/
setAriaLabelledby() {
if (!isDocumentAvailable()) {
return;
}
const component = this.getFocusableComponent();
if (component && component.focusableId) {
const rootElement = getRootElement(this.label.nativeElement);
const labelTarget = rootElement.querySelector(`#${component.focusableId}`);
const labelElement = this.label.nativeElement;
const id = labelElement.id || `k-${guid()}`;
if (!labelElement.getAttribute('id')) {
this.renderer.setAttribute(labelElement, 'id', id);
}
// Editor in iframe mode needs special treatment
if (component.focusableId.startsWith('k-editor') && component.iframe) {
component.contentAreaLoaded.subscribe(() => {
this.zone.runOutsideAngular(() => {
setTimeout(() => {
const editableElement = component.container.element.nativeElement.contentDocument.body.firstElementChild;
this.renderer.setAttribute(editableElement, 'aria-label', labelElement.textContent);
});
});
});
}
if (!labelTarget) {
return;
}
const existingAriaLabelledBy = labelTarget.hasAttribute('aria-labelledby') && labelTarget.getAttribute('aria-labelledby');
// DropDowns with focusable input elements rely on the aria-labelledby attribute to set the same attribute on their popup listbox element
// On the other hand, the aria-labelledby attribute is redundant on the Input element when there is label[for] association -
// https://feedback.telerik.com/kendo-angular-ui/1648203-remove-aria-labelledby-when-native-html-elements-are-associated.
// This addresses both cases, setting a special data-kendo-label-id attribute to be used internally by other components when the aria-describedby one is not applicable.
this.renderer.setAttribute(labelTarget, nativeLabelForTargets.includes(labelTarget.tagName) ? 'data-kendo-label-id' : 'aria-labelledby', existingAriaLabelledBy && existingAriaLabelledBy !== id ? `${existingAriaLabelledBy} ${id}` : id);
}
}
getFocusableComponent() {
const target = this.for;
return target && target.focus !== undefined ? target : null;
}
handleClick = () => {
const component = this.getFocusableComponent();
if (!component) {
return;
}
if (component.focus) {
component.focus();
}
};
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LabelDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LabelDirective, isStandalone: true, selector: "label[for]", inputs: { for: "for", labelClass: "labelClass" }, host: { properties: { "attr.for": "this.labelFor", "class.k-label": "this.labelClass" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LabelDirective, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'label[for]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }]; }, propDecorators: { for: [{
type: Input
}], labelFor: [{
type: HostBinding,
args: ['attr.for']
}], labelClass: [{
type: Input
}, {
type: HostBinding,
args: ['class.k-label']
}] } });
/**
* @hidden
*/
const packageMetadata = {
name: '@progress/kendo-angular-label',
productName: 'Kendo UI for Angular',
productCode: 'KENDOUIANGULAR',
productCodes: ['KENDOUIANGULAR'],
publishDate: 1751463045,
version: '19.2.0',
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
};
/**
* @hidden
*/
class FloatingLabelInputAdapter {
component;
onFocus;
onBlur;
autoFillStart;
autoFillEnd;
onValueChange;
get focusableId() {
const component = this.component;
if ('focusableId' in component) {
return component.focusableId;
}
else if ('id' in component) {
return component.id;
}
return "";
}
set focusableId(value) {
const component = this.component;
if ('focusableId' in component) {
component.focusableId = value;
}
else if ('id' in component) {
component.id = value;
}
}
constructor(component, formControl) {
this.component = component;
const isObservableOrEventEmitter = (event) => event instanceof Observable || event instanceof EventEmitter;
if (isObservableOrEventEmitter(component.onFocus)) {
this.onFocus = component.onFocus;
}
if (isObservableOrEventEmitter(component.autoFillStart)) {
this.autoFillStart = component.autoFillStart;
}
if (isObservableOrEventEmitter(component.autoFillEnd)) {
this.autoFillEnd = component.autoFillEnd;
}
if (isObservableOrEventEmitter(component.onBlur)) {
this.onBlur = component.onBlur;
}
if (formControl) {
this.onValueChange = formControl.valueChanges;
}
else if (component.valueChange) {
this.onValueChange = component.valueChange;
}
}
}
/**
* @hidden
*/
class Messages extends ComponentMessages {
/**
* The optional text.
*/
optional;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: Messages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: Messages, selector: "kendo-label-messages-base", inputs: { optional: "optional" }, usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: Messages, decorators: [{
type: Directive,
args: [{
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'kendo-label-messages-base'
}]
}], propDecorators: { optional: [{
type: Input
}] } });
/**
* @hidden
*/
class LocalizedMessagesDirective extends Messages {
service;
constructor(service) {
super();
this.service = service;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedMessagesDirective, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: LocalizedMessagesDirective, isStandalone: true, selector: "\n [kendoLabelLocalizedMessages],\n [kendoFloatingLabelLocalizedMessages]\n ", providers: [
{
provide: Messages,
useExisting: forwardRef(() => LocalizedMessagesDirective)
}
], usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocalizedMessagesDirective, decorators: [{
type: Directive,
args: [{
providers: [
{
provide: Messages,
useExisting: forwardRef(() => LocalizedMessagesDirective)
}
],
selector: `
[kendoLabelLocalizedMessages],
[kendoFloatingLabelLocalizedMessages]
`,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
const isFunction = (x) => Object.prototype.toString.call(x) === '[object Function]';
/**
* Represents the [Kendo UI FloatingLabel component for Angular]({% slug overview_floatinglabel %}).
* Use this component to provide floating labels to `input` elements.
*
* The FloatingLabel supports Template and Reactive Forms.
* You can use it with Kendo UI for Angular Inputs components such as `kendo-combobox`, `kendo-numerictextbox`, or `kendo-textbox`.
* [See example.](slug:associate_floatinglabel)
*
* @example
* ```html
* <kendo-floatinglabel text="First name">
* <kendo-textbox></kendo-textbox>
* </kendo-floatinglabel>
* ```
*
* @remarks
* Supported children components are: {@link CustomMessagesComponent}.
*/
class FloatingLabelComponent {
elementRef;
renderer;
changeDetectorRef;
localization;
/**
* Gets the current floating label position.
*/
get labelPosition() {
if (!this.empty) {
return 'Out';
}
return this.focused ? 'Out' : 'In';
}
hostClasses = true;
get focusedClass() {
return this.focused;
}
get invalidClass() {
return this.invalid;
}
/**
* @hidden
*/
direction;
/**
* Sets the CSS styles for the internal label element.
* Accepts values supported by the [`ngStyle`](link:site.data.urls.angular['ngstyleapi']) directive.
*/
labelCssStyle;
/**
* Sets the CSS classes for the label element.
* Accepts values supported by the [`ngClass`](link:site.data.urls.angular['ngclassapi']) directive.
*/
labelCssClass;
/**
* Sets the `id` attribute of the input inside the floating label.
*/
id;
/**
* Sets the text content of the floating label that describes the input.
*/
text;
/**
* Marks a form field as optional. When enabled, renders the `Optional` text by default.
* You can customize the text by providing a custom message ([see example]({% slug label_globalization %}#toc-custom-messages)).
*
* @default false
*/
optional;
/**
* Fires after the FloatingLabel position changes.
*/
positionChange = new EventEmitter();
kendoInput;
formControl;
/**
* @hidden
*/
focused = false;
/**
* @hidden
*/
empty = true;
/**
* @hidden
*/
invalid = false;
/**
* @hidden
*/
labelId = `k-${guid()}`;
subscription;
autoFillStarted = false;
constructor(elementRef, renderer, changeDetectorRef, localization) {
this.elementRef = elementRef;
this.renderer = renderer;
this.changeDetectorRef = changeDetectorRef;
this.localization = localization;
validatePackage(packageMetadata);
this.direction = localization.rtl ? 'rtl' : 'ltr';
this.renderer.removeAttribute(this.elementRef.nativeElement, "id");
}
/**
* @hidden
*/
ngAfterContentInit() {
if (!isDocumentAvailable()) {
return;
}
this.validateSetup();
const control = new FloatingLabelInputAdapter(this.kendoInput || this.formControl.valueAccessor, this.formControl);
this.addHandlers(control);
this.setLabelFor(control);
}
ngAfterViewInit() {
if (this.kendoInput) {
this.setAriaLabelledby(this.kendoInput);
}
}
/**
* @hidden
*/
ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
/**
* @hidden
*/
textFor(key) {
return this.localization.get(key);
}
subscribe(control, eventName, handler) {
if (control[eventName] instanceof EventEmitter) {
const subscription = control[eventName].subscribe(handler);
if (!this.subscription) {
this.subscription = subscription;
}
else {
this.subscription.add(subscription);
}
}
}
updateState() {
const empty = value => {
// zero is not an empty value (e.g., NumericTextBox)
if (value === 0 || value === false) {
return false;
}
// empty arrays are an empty value (e.g., MultiSelect)
if (Array.isArray(value) && !value.length) {
return true;
}
return !value;
};
const formControl = this.formControl;
if (formControl) {
const valueAccessor = formControl.valueAccessor;
if (isFunction(valueAccessor.isEmpty)) {
this.empty = valueAccessor.isEmpty();
}
else {
this.empty = empty(formControl.value);
}
this.invalid = formControl.invalid && (formControl.touched || formControl.dirty);
}
else {
this.empty = isFunction(this.kendoInput.isEmpty) ?
this.kendoInput.isEmpty() : empty(this.kendoInput.value);
}
if (this.empty) {
this.renderer.addClass(this.elementRef.nativeElement, 'k-empty');
}
else {
this.renderer.removeClass(this.elementRef.nativeElement, 'k-empty');
}
this.changeDetectorRef.markForCheck();
}
setAriaLabelledby(component) {
const componentId = component.focusableId || component.id;
if (componentId) {
const focusableElement = this.elementRef.nativeElement.querySelector(`#${componentId}`);
if (!focusableElement) {
return;
}
const existingAriaLabelledBy = focusableElement.hasAttribute('aria-labelledby') && focusableElement.getAttribute('aria-labelledby');
// DropDowns with focusable input elements rely on the aria-labelledby attribute to set the same attribute on their popup listbox element.
// On the other hand, the aria-labelledby attribute is redundant on the Input element when there is label[for] association -
// https://feedback.telerik.com/kendo-angular-ui/1648203-remove-aria-labelledby-when-native-html-elements-are-associated.
// This addresses both cases, setting a special data-kendo-label-id attribute to be used internally by other components when the aria-describedby one is not applicable.
this.renderer.setAttribute(focusableElement, nativeLabelForTargets.includes(focusableElement.tagName) ?
'data-kendo-label-id' : 'aria-labelledby', existingAriaLabelledBy && existingAriaLabelledBy !== this.labelId ? `${existingAriaLabelledBy} ${this.labelId}` : this.labelId);
}
}
setLabelFor(control) {
const controlId = control.focusableId || control.id;
if (this.id && controlId) {
// input wins
this.id = controlId;
}
else if (this.id) {
control.focusableId = this.id;
}
else if (controlId) {
this.id = controlId;
}
else {
const id = `k-${guid()}`;
control.focusableId = id;
this.id = id;
}
}
handleAutofill(control) {
this.subscribe(control, 'autoFillStart', () => {
this.autoFillStarted = true;
this.renderer.removeClass(this.elementRef.nativeElement, 'k-empty');
});
this.subscribe(control, 'autoFillEnd', () => {
if (this.autoFillStarted) {
this.autoFillStarted = false;
if (this.empty) {
this.renderer.addClass(this.elementRef.nativeElement, 'k-empty');
}
}
});
}
addHandlers(control) {
const setFocus = (isFocused) => () => {
this.focused = isFocused;
this.updateState();
if (!this.empty) {
return;
}
if (hasObservers(this.positionChange)) {
this.positionChange.emit(isFocused ? 'Out' : 'In');
}
};
this.subscribe(control, 'onFocus', setFocus(true));
this.subscribe(control, 'onBlur', setFocus(false));
this.handleAutofill(control);
const updateState = () => this.updateState();
updateState();
this.subscribe(control, 'onValueChange', updateState);
}
validateSetup() {
if (!this.formControl && !this.kendoInput) {
if (isDevMode()) {
throw new Error("The FloatingLabelComponent requires a Kendo Input component" +
" or a forms-bound component to function properly.");
}
return;
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FloatingLabelComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FloatingLabelComponent, isStandalone: true, selector: "kendo-floatinglabel", inputs: { labelCssStyle: "labelCssStyle", labelCssClass: "labelCssClass", id: "id", text: "text", optional: "optional" }, outputs: { positionChange: "positionChange" }, host: { properties: { "class.k-floating-label-container": "this.hostClasses", "class.k-focus": "this.focusedClass", "class.k-invalid": "this.invalidClass", "attr.dir": "this.direction" } }, providers: [
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.floatinglabel'
}
], queries: [{ propertyName: "kendoInput", first: true, predicate: KendoInput, descendants: true }, { propertyName: "formControl", first: true, predicate: NgControl, descendants: true }], exportAs: ["kendoFloatingLabel"], ngImport: i0, template: `
<ng-container kendoFloatingLabelLocalizedMessages
i18n-optional="kendo.floatinglabel.optional|The text for the optional segment of a FloatingLabel component"
optional="Optional"
>
</ng-container>
<ng-content></ng-content>
<label *ngIf="text" [ngClass]="labelCssClass" [ngStyle]="labelCssStyle" [for]="id" [attr.id]="labelId" class="k-floating-label">
{{ text }}<span *ngIf="optional" class="k-label-optional">({{textFor('optional')}})</span>
</label>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "\n [kendoLabelLocalizedMessages],\n [kendoFloatingLabelLocalizedMessages]\n " }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FloatingLabelComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-floatinglabel',
exportAs: 'kendoFloatingLabel',
providers: [
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.floatinglabel'
}
],
template: `
<ng-container kendoFloatingLabelLocalizedMessages
i18n-optional="kendo.floatinglabel.optional|The text for the optional segment of a FloatingLabel component"
optional="Optional"
>
</ng-container>
<ng-content></ng-content>
<label *ngIf="text" [ngClass]="labelCssClass" [ngStyle]="labelCssStyle" [for]="id" [attr.id]="labelId" class="k-floating-label">
{{ text }}<span *ngIf="optional" class="k-label-optional">({{textFor('optional')}})</span>
</label>
`,
standalone: true,
imports: [LocalizedMessagesDirective, NgIf, NgClass, NgStyle]
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i1.LocalizationService }]; }, propDecorators: { hostClasses: [{
type: HostBinding,
args: ['class.k-floating-label-container']
}], focusedClass: [{
type: HostBinding,
args: ['class.k-focus']
}], invalidClass: [{
type: HostBinding,
args: ['class.k-invalid']
}], direction: [{
type: HostBinding,
args: ['attr.dir']
}], labelCssStyle: [{
type: Input
}], labelCssClass: [{
type: Input
}], id: [{
type: Input
}], text: [{
type: Input
}], optional: [{
type: Input
}], positionChange: [{
type: Output
}], kendoInput: [{
type: ContentChild,
args: [KendoInput, { static: false }]
}], formControl: [{
type: ContentChild,
args: [NgControl, { static: false }]
}] } });
/**
* Represents the [Kendo UI Label component for Angular]({% slug overview_label %}).
*
* Use the `LabelComponent` to associate a label with input elements or components.
*
* @example
* ```html
* <kendo-label [for]="input" text="First name">
* <kendo-textbox #input></kendo-textbox>
* </kendo-label>
* ```
* @remarks
* Supported children components are: {@link CustomMessagesComponent}.
*/
class LabelComponent {
elementRef;
renderer;
localization;
/**
* Specifies the `dir` attribute value for the component.
* @hidden
*/
direction;
/**
* Sets the text content of the Label. Use this property to describe the input.
*
* @example
* ```html
* <kendo-label text="Email"></kendo-label>
* ```
*/
text;
/**
* Associates the label with a component by a template reference or with an HTML element by `id`.
*
* @example
* ```html
* <input #myInput />
* <kendo-label [for]="myInput" text="Username"></kendo-label>
* ```
*/
set for(forValue) {
if (forValue !== this._for) {
this._for = forValue;
this.control = forValue;
}
}
get for() {
return this._for;
}
/**
* Marks a form field as optional. When enabled, the label displays the `Optional` text by default.
* You can customize the text by providing a custom message. ([See example]({% slug label_globalization %}#toc-custom-messages)).
*
* @default false
* @example
* ```html
* <kendo-label text="Phone" [optional]="true"></kendo-label>
* ```
*/
optional;
/**
* Sets the CSS styles for the label element.
* Accepts values supported by the [`ngStyle`](link:site.data.urls.angular['ngstyleapi']) directive.
*
* @example
* ```html
* <kendo-label text="Name" [labelCssStyle]="{ color: 'red' }"></kendo-label>
* ```
*/
labelCssStyle;
/**
* Sets the CSS classes for the label element.
* Accepts values supported by the [`ngClass`](link:site.data.urls.angular['ngclassapi']) directive.
*
* @example
* ```html
* <kendo-label text="Address" [labelCssClass]="'custom-label'"></kendo-label>
* ```
*/
labelCssClass;
labelDirective;
kendoInput;
/**
* @hidden
*/
control;
subscriptions = new Subscription();
_for;
constructor(elementRef, renderer, localization) {
this.elementRef = elementRef;
this.renderer = renderer;
this.localization = localization;
validatePackage(packageMetadata);
this.direction = localization.rtl ? 'rtl' : 'ltr';
this.renderer.removeAttribute(this.elementRef.nativeElement, 'id');
}
/**
* @hidden
*/
ngAfterContentInit() {
if (this.for) {
return;
}
const wrappedNativeInput = getWrappedNativeInput(this.elementRef.nativeElement);
if (wrappedNativeInput) {
if (!wrappedNativeInput.hasAttribute('id')) {
this.renderer.setAttribute(wrappedNativeInput, 'id', `k-${guid()}`);
}
this.control = wrappedNativeInput;
return;
}
this.control = this.kendoInput;
}
/**
* @hidden
*/
ngOnInit() {
this.subscriptions.add(this.localization.changes.subscribe(({ rtl }) => {
this.direction = rtl ? 'rtl' : 'ltr';
}));
}
/**
* @hidden
*/
ngAfterViewInit() {
this.labelDirective.setAriaLabelledby();
}
/**
* @hidden
*/
ngOnDestroy() {
if (this.subscriptions) {
this.subscriptions.unsubscribe();
}
}
/**
* @hidden
*/
textFor(key) {
return this.localization.get(key);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LabelComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: LabelComponent, isStandalone: true, selector: "kendo-label", inputs: { text: "text", for: "for", optional: "optional", labelCssStyle: "labelCssStyle", labelCssClass: "labelCssClass" }, host: { properties: { "attr.dir": "this.direction" } }, providers: [
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.label'
}
], queries: [{ propertyName: "kendoInput", first: true, predicate: KendoInput, descendants: true, static: true }], viewQueries: [{ propertyName: "labelDirective", first: true, predicate: LabelDirective, descendants: true, static: true }], exportAs: ["kendoLabel"], ngImport: i0, template: `
<ng-container kendoLabelLocalizedMessages
i18n-optional="kendo.label.optional|The text for the optional segment of a Label component"
optional="Optional"
>
</ng-container>
<label
[for]="control"
[class.k-label-empty]="!text"
[ngClass]="labelCssClass"
[ngStyle]="labelCssStyle"
>
{{ text }}<span *ngIf="optional" class="k-label-optional">({{textFor('optional')}})</span>
</label>
<ng-content></ng-content>
`, isInline: true, dependencies: [{ kind: "directive", type: LocalizedMessagesDirective, selector: "\n [kendoLabelLocalizedMessages],\n [kendoFloatingLabelLocalizedMessages]\n " }, { kind: "directive", type: LabelDirective, selector: "label[for]", inputs: ["for", "labelClass"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LabelComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-label',
exportAs: 'kendoLabel',
providers: [
LocalizationService,
{
provide: L10N_PREFIX,
useValue: 'kendo.label'
}
],
template: `
<ng-container kendoLabelLocalizedMessages
i18n-optional="kendo.label.optional|The text for the optional segment of a Label component"
optional="Optional"
>
</ng-container>
<label
[for]="control"
[class.k-label-empty]="!text"
[ngClass]="labelCssClass"
[ngStyle]="labelCssStyle"
>
{{ text }}<span *ngIf="optional" class="k-label-optional">({{textFor('optional')}})</span>
</label>
<ng-content></ng-content>
`,
standalone: true,
imports: [LocalizedMessagesDirective, LabelDirective, NgClass, NgStyle, NgIf]
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.LocalizationService }]; }, propDecorators: { direction: [{
type: HostBinding,
args: ['attr.dir']
}], text: [{
type: Input
}], for: [{
type: Input
}], optional: [{
type: Input
}], labelCssStyle: [{
type: Input
}], labelCssClass: [{
type: Input
}], labelDirective: [{
type: ViewChild,
args: [LabelDirective, { static: true }]
}], kendoInput: [{
type: ContentChild,
args: [KendoInput, { static: true }]
}] } });
/**
* Use the `CustomMessagesComponent` to override default component messages. ([See example](slug:label_globalization#toc-internationalization))
*
*/
class CustomMessagesComponent extends Messages {
service;
constructor(service) {
super();
this.service = service;
}
get override() {
return true;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CustomMessagesComponent, deps: [{ token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: CustomMessagesComponent, isStandalone: true, selector: "kendo-label-messages, kendo-floatinglabel-messages", providers: [
{
provide: Messages,
useExisting: forwardRef(() => CustomMessagesComponent)
}
], usesInheritance: true, ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CustomMessagesComponent, decorators: [{
type: Component,
args: [{
providers: [
{
provide: Messages,
useExisting: forwardRef(() => CustomMessagesComponent)
}
],
selector: 'kendo-label-messages, kendo-floatinglabel-messages',
template: ``,
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.LocalizationService }]; } });
/**
* Holds all `Label`-related components and directives.
*
* @example
* ```typescript
* import { KENDO_LABEL } from '@progress/kendo-angular-label';
* ```
*/
const KENDO_LABEL = [
LabelDirective,
LabelComponent,
CustomMessagesComponent
];
/**
* Holds all `FloatingLabel`-related components and directives.
*
* @example
* ```typescript
* import { KENDO_FLOATINGLABEL } from '@progress/kendo-angular-label';
* ```
*/
const KENDO_FLOATINGLABEL = [
FloatingLabelComponent,
CustomMessagesComponent
];
/**
* Holds all `@progress/kendo-angular-label`-related components and directives.
*
* @example
* ```typescript
* import { KENDO_LABELS } from '@progress/kendo-angular-label';
* ```
*/
const KENDO_LABELS = [
...KENDO_LABEL,
...KENDO_FLOATINGLABEL
];
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [`NgModule`](link:site.data.urls.angular['ngmoduleapi']) definition for the Label component.
* The module imports:
* - `LabelDirective`
* - `LabelComponent`
* - `FloatingLabel`
*
* @example
* ```ts
* import { LabelModule } from '@progress/kendo-angular-label';
* import { NgModule } from '@angular/core';
* import { AppComponent } from './app.component';
*
* @NgModule({
* declarations: [AppComponent],
* imports: [BrowserModule, LabelModule],
* bootstrap: [AppComponent]
* })
* export class AppModule {}
* ```
*/
class LabelModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LabelModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: LabelModule, imports: [LabelDirective, LabelComponent, CustomMessagesComponent, FloatingLabelComponent, CustomMessagesComponent], exports: [LabelDirective, LabelComponent, CustomMessagesComponent, FloatingLabelComponent, CustomMessagesComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LabelModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LabelModule, decorators: [{
type: NgModule,
args: [{
imports: [...KENDO_LABELS],
exports: [...KENDO_LABELS]
}]
}] });
//IMPORTANT: NgModule export kept for backwards compatibility
/**
* Represents the [`NgModule`](link:site.data.urls.angular['ngmoduleapi']) definition for the FloatingLabel component.
*
* @example
* ```typescript
* import { FloatingLabelModule } from '@progress/kendo-angular-label';
*
* @NgModule({
* imports: [BrowserModule, FloatingLabelModule],
* declarations: [AppComponent],
* bootstrap: [AppComponent]
* })
* export class AppModule { }
* ```
*/
class FloatingLabelModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FloatingLabelModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: FloatingLabelModule, imports: [FloatingLabelComponent, CustomMessagesComponent], exports: [FloatingLabelComponent, CustomMessagesComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FloatingLabelModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FloatingLabelModule, decorators: [{
type: NgModule,
args: [{
exports: [...KENDO_FLOATINGLABEL],
imports: [...KENDO_FLOATINGLABEL]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { CustomMessagesComponent, FloatingLabelComponent, FloatingLabelModule, KENDO_FLOATINGLABEL, KENDO_LABEL, KENDO_LABELS, LabelComponent, LabelDirective, LabelModule, LocalizedMessagesDirective };