igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
496 lines (440 loc) • 14.7 kB
text/typescript
import { DOCUMENT, NgIf, NgTemplateOutlet, NgClass, NgSwitch, NgSwitchCase, NgSwitchDefault } from '@angular/common';
import {
AfterViewChecked, ChangeDetectorRef, Component,
ContentChild,
ContentChildren,
ElementRef,
HostBinding,
HostListener, Inject, Input,
OnDestroy, Optional, QueryList
} from '@angular/core';
import { Subject, Subscription } from 'rxjs';
import {
DisplayDensity, DisplayDensityBase, DisplayDensityToken, IDisplayDensityOptions
} from '../core/density';
import { IInputResourceStrings } from '../core/i18n/input-resources';
import { CurrentResourceStrings } from '../core/i18n/resources';
import { mkenum, PlatformUtil } from '../core/utils';
import { IgxButtonDirective } from '../directives/button/button.directive';
import { IgxHintDirective } from '../directives/hint/hint.directive';
import {
IgxInputDirective,
IgxInputState
} from '../directives/input/input.directive';
import { IgxPrefixDirective } from '../directives/prefix/prefix.directive';
import { IgxSuffixDirective } from '../directives/suffix/suffix.directive';
import { IgxInputGroupBase } from './input-group.common';
import { IgxInputGroupType, IGX_INPUT_GROUP_TYPE } from './inputGroupType';
import { IgxIconComponent } from '../icon/icon.component';
const IgxInputGroupTheme = mkenum({
Material: 'material',
Fluent: 'fluent',
Bootstrap: 'bootstrap',
IndigoDesign: 'indigo-design'
});
/**
* Determines the Input Group theme.
*/
export type IgxInputGroupTheme = (typeof IgxInputGroupTheme)[keyof typeof IgxInputGroupTheme];
export class IgxInputGroupComponent extends DisplayDensityBase implements IgxInputGroupBase, AfterViewChecked, OnDestroy {
/**
* Sets the resource strings.
* By default it uses EN resources.
*/
public set resourceStrings(value: IInputResourceStrings) {
this._resourceStrings = Object.assign({}, this._resourceStrings, value);
}
/**
* Returns the resource strings.
*/
public get resourceStrings(): IInputResourceStrings {
return this._resourceStrings;
}
/**
* Property that enables/disables the auto-generated class of the `IgxInputGroupComponent`.
* By default applied the class is applied.
* ```typescript
* @ViewChild("MyInputGroup")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* this.inputGroup.defaultClass = false;
* ```
* }
*/
public defaultClass = true;
/** @hidden */
public hasPlaceholder = false;
/** @hidden */
public isRequired = false;
/** @hidden */
public isFocused = false;
/**
* @hidden @internal
* When truthy, disables the `IgxInputGroupComponent`.
* Controlled by the underlying `IgxInputDirective`.
* ```html
* <igx-input-group [disabled]="true"></igx-input-group>
* ```
*/
public disabled = false;
/**
* Prevents automatically focusing the input when clicking on other elements in the input group (e.g. prefix or suffix).
*
* @remarks Automatic focus causes software keyboard to show on mobile devices.
*
* @example
* ```html
* <igx-input-group [suppressInputAutofocus]="true"></igx-input-group>
* ```
*/
public suppressInputAutofocus = false;
/** @hidden */
public hasWarning = false;
/** @hidden */
protected hints: QueryList<IgxHintDirective>;
protected _prefixes: QueryList<IgxPrefixDirective>;
protected _suffixes: QueryList<IgxSuffixDirective>;
/** @hidden */
protected input: IgxInputDirective;
private _type: IgxInputGroupType = null;
private _filled = false;
private _theme: IgxInputGroupTheme;
private _theme$ = new Subject();
private _subscription: Subscription;
private _resourceStrings = CurrentResourceStrings.InputResStrings;
/** @hidden */
public get validClass(): boolean {
return this.input.valid === IgxInputState.VALID;
}
/** @hidden */
public get invalidClass(): boolean {
return this.input.valid === IgxInputState.INVALID;
}
/** @hidden */
public get isFilled() {
return this._filled || (this.input && this.input.value);
}
/** @hidden */
public get isDisplayDensityCosy() {
return this.displayDensity === DisplayDensity.cosy;
}
/** @hidden */
public get isDisplayDensityComfortable() {
return this.displayDensity === DisplayDensity.comfortable;
}
/** @hidden */
public get isDisplayDensityCompact() {
return this.displayDensity === DisplayDensity.compact;
}
/** @hidden */
public get textAreaClass(): boolean {
return this.input.isTextArea;
}
/**
* An @Input property that sets how the input will be styled.
* Allowed values of type IgxInputGroupType.
* ```html
* <igx-input-group [type]="'search'">
* ```
*/
public set type(value: IgxInputGroupType) {
this._type = value;
}
/**
* Returns the type of the `IgxInputGroupComponent`. How the input is styled.
* The default is `line`.
* ```typescript
* @ViewChild("MyInputGroup")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let inputType = this.inputGroup.type;
* }
* ```
*/
public get type() {
return this._type || this._inputGroupType || 'line';
}
/**
* Sets the theme of the input.
* Allowed values of type IgxInputGroupTheme.
* ```typescript
* @ViewChild("MyInputGroup")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit() {
* let inputTheme = 'fluent';
* }
*/
public set theme(value: IgxInputGroupTheme) {
this._theme = value;
}
/**
* Returns the theme of the input.
* The returned value is of type IgxInputGroupType.
* ```typescript
* @ViewChild("MyInputGroup")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit() {
* let inputTheme = this.inputGroup.theme;
* }
*/
public get theme(): IgxInputGroupTheme {
return this._theme;
}
constructor(
public element: ElementRef<HTMLElement>,
_displayDensityOptions: IDisplayDensityOptions,
private _inputGroupType: IgxInputGroupType,
private document: any,
private platform: PlatformUtil,
private cdr: ChangeDetectorRef
) {
super(_displayDensityOptions);
this._subscription = this._theme$.asObservable().subscribe(value => {
this._theme = value as IgxInputGroupTheme;
this.cdr.detectChanges();
});
}
/** @hidden */
public onClick(event: MouseEvent) {
if (
!this.isFocused &&
event.target !== this.input.nativeElement &&
!this.suppressInputAutofocus
) {
this.input.focus();
}
}
/** @hidden */
public onPointerDown(event: PointerEvent) {
if (this.isFocused && event.target !== this.input.nativeElement) {
event.preventDefault();
}
}
/** @hidden @internal */
public hintClickHandler(event: MouseEvent) {
event.stopPropagation();
}
/**
* Returns whether the `IgxInputGroupComponent` has hints.
* ```typescript
* @ViewChild("MyInputGroup")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let inputHints = this.inputGroup.hasHints;
* }
* ```
*/
public get hasHints() {
return this.hints.length > 0;
}
/** @hidden @internal */
public get hasPrefixes() {
return this._prefixes.length > 0 || this.isFileType;
}
/** @hidden @internal */
public set prefixes(items: QueryList<IgxPrefixDirective>) {
this._prefixes = items;
}
/** @hidden @internal */
public get hasSuffixes() {
return this._suffixes.length > 0 || this.isFileType && this.isFilled;
}
/** @hidden @internal */
public set suffixes(items: QueryList<IgxPrefixDirective>) {
this._suffixes = items;
}
/**
* Returns whether the `IgxInputGroupComponent` has border.
* ```typescript
* @ViewChild("MyInputGroup")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let inputBorder = this.inputGroup.hasBorder;
* }
* ```
*/
public get hasBorder() {
return (
(this.type === 'line' || this.type === 'box') &&
this._theme === 'material'
);
}
/**
* Returns whether the `IgxInputGroupComponent` type is line.
* ```typescript
* @ViewChild("MyInputGroup1")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let isTypeLine = this.inputGroup.isTypeLine;
* }
* ```
*/
public get isTypeLine(): boolean {
return this.type === 'line' && this._theme === 'material';
}
/**
* Returns whether the `IgxInputGroupComponent` type is box.
* ```typescript
* @ViewChild("MyInputGroup1")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let isTypeBox = this.inputGroup.isTypeBox;
* }
* ```
*/
public get isTypeBox() {
return this.type === 'box' && this._theme === 'material';
}
/** @hidden @internal */
public uploadButtonHandler() {
this.input.nativeElement.click();
}
/** @hidden @internal */
public clearValueHandler() {
this.input.clear();
}
/** @hidden @internal */
public get isFileType() {
return this.input.type === 'file';
}
/** @hidden @internal */
public get fileNames() {
return this.input.fileNames || this._resourceStrings.igx_input_file_placeholder;
}
/**
* Returns whether the `IgxInputGroupComponent` type is border.
* ```typescript
* @ViewChild("MyInputGroup1")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let isTypeBorder = this.inputGroup.isTypeBorder;
* }
* ```
*/
public get isTypeBorder() {
return this.type === 'border' && this._theme === 'material';
}
/**
* Returns true if the `IgxInputGroupComponent` theme is Fluent.
* ```typescript
* @ViewChild("MyInputGroup1")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let isTypeFluent = this.inputGroup.isTypeFluent;
* }
* ```
*/
public get isTypeFluent() {
return this._theme === 'fluent';
}
/**
* Returns true if the `IgxInputGroupComponent` theme is Bootstrap.
* ```typescript
* @ViewChild("MyInputGroup1")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let isTypeBootstrap = this.inputGroup.isTypeBootstrap;
* }
* ```
*/
public get isTypeBootstrap() {
return this._theme === 'bootstrap';
}
/**
* Returns true if the `IgxInputGroupComponent` theme is Indigo.
* ```typescript
* @ViewChild("MyInputGroup1")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let isTypeIndigo = this.inputGroup.isTypeIndigo;
* }
* ```
*/
public get isTypeIndigo() {
return this._theme === 'indigo-design';
}
/**
* Returns whether the `IgxInputGroupComponent` type is search.
* ```typescript
* @ViewChild("MyInputGroup1")
* public inputGroup: IgxInputGroupComponent;
* ngAfterViewInit(){
* let isTypeSearch = this.inputGroup.isTypeSearch;
* }
* ```
*/
public get isTypeSearch() {
return this.type === 'search';
}
/** @hidden */
public get filled() {
return this._filled;
}
/** @hidden */
public set filled(val) {
this._filled = val;
}
/** @hidden @internal */
public ngAfterViewChecked() {
if (!this._theme) {
const cssProp = this.document.defaultView
.getComputedStyle(this.element.nativeElement)
.getPropertyValue('--theme')
.trim();
if(cssProp !== '') {
Promise.resolve().then(() => {
this._theme$.next(cssProp);
this.cdr.markForCheck();
});
}
}
}
/** @hidden @internal */
public ngOnDestroy() {
this._subscription.unsubscribe();
}
}