projects/congarevenuecloud/elements/src/lib/input-field/input-field.component.ts
The Input field component displays the field values as a radio button, checkbox, dropdown, a text area or a label value, depending upon the field type.
import { InputFieldModule } from '@congarevenuecloud/elements';
@NgModule({
imports: [InputFieldModule, ...]
})
export class AppModule {}
// Basic Usage
```typescript
<apt-input-field
[(ngModel)]="myModel"
[field]="fieldApiName"
[entity]="entityApiName"
></apt-input-field>
// All inputs and outputs
```typescript
<apt-input-field
[(ngModel)]="myModel"
(ngModelChange)="handleChange($event)"
[field]="fieldApiName"
[entity]="entityApiName"
[label]="label"
[readonly]="isReadOnly"
[allowEmpty]="allowEmpty"
[disabledValues]="disabledValues"
[hiddenValues]="hiddenValues"
[inline]="isInline"
[inputSize]="'small'"
[rows]="2"
[placeholder]="myPlaceholder"
[required]="true"
[errorMsg]="errorMessage"
[showLabel]="true"
[labelClass]="labelClass"
[filterValues]="filterValues"
[hideOptions]="true"
[hide]="true"
[defaultValue]="true"
[enableValues]="values"
[lookupOptions]="lookupOptions"
></apt-input-field>
ControlValueAccessor
OnChanges
OnDestroy
changeDetection | ChangeDetectionStrategy.OnPush |
encapsulation | ViewEncapsulation.None |
providers |
{
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputFieldComponent), multi: true,
}
|
selector | apt-input-field |
styleUrls | ./input-field.component.scss |
templateUrl | ./input-field.component.html |
constructor(translateService: TranslateService, aobjectService: AObjectService, cdr: ChangeDetectorRef, metadataService: MetadataService, apiService: ApiService)
|
||||||||||||||||||
Parameters :
|
allowClearableLookups |
Type : boolean
|
Default value : true
|
Boolean specifies whether the lookup values in the select component can be cleared.
When set to |
allowEmpty |
Type : boolean
|
Default value : false
|
Flag to allow this input to be empty. |
asterisk |
Type : boolean
|
Default value : true
|
Flag to show the asterisk on a field. |
defaultValue |
Type : boolean
|
Boolean value when set to true will populate the incoming field with default value |
disabledValues |
Type : Set<string>
|
Default value : new Set<string>()
|
Set of disabled values. |
displayFieldType |
Type : "radio" | "dropdown"
|
The property is responsible to override the input field as type 'radio' for metadata type boolean and 'dropdown' for the metadata type multipicklist. |
enableValues |
Type : Array<string>
|
List of enabled values for multipicklist. |
entity |
Type : AObject
|
Represents an AObject instance |
errorMsg |
Type : string
|
Property to show error message |
field |
Type : string
|
Represents the field name type of string for the AObject. |
fieldType |
Type : string
|
The property overrides the default type of the field to render the corresponding input field. |
filterValues |
Type : Array<string>
|
The list of values to be set in the picklist. |
hiddenValues |
Type : Set<string>
|
Default value : new Set<string>()
|
Set of hidden values. |
hide |
Type : boolean
|
Default value : false
|
Boolean value to show or hide the component. |
hideOptions |
Type : boolean
|
Default value : false
|
Boolean value to show default picklist values or not. |
inline |
Type : boolean
|
Default value : false
|
Flag to set this input as inline. |
label |
Type : string
|
The override default values for the input Label. |
labelClass |
Type : string
|
To override the default styling of input field label, set the bootstrap classes of type string. Ex: 'mb-1' |
lookupObjectName |
Type : string
|
Name of the lookupObject of type string. |
lookupOptions |
Type : LookupOptions
|
Object to set primary text field, secondary text field, thumbnail field, conditions, filters etc |
minVal |
Type : number
|
Default value : 1
|
set minimum value for the number field of type 'double'. |
multiple |
Type : boolean
|
Default value : false
|
Flag to set the picklist to a multipicklist |
overrideDefaultFormValidation |
Type : boolean
|
Default value : false
|
Boolean when set to true overrides default form validaion. Defaulted to false. |
picklistValues |
Type : Array<ComplexArray>
|
Array of ComplexArray type as picklist values |
placeholder |
Type : string
|
Default value : ''
|
Placeholder string for the input. |
presetBoolean |
Type : boolean
|
Default value : false
|
Flag allows boolean dropdown values to be preset. |
presetBooleanLabel |
Type : string
|
Default value : ''
|
Preset label to be shown if presetBoolean is set to true. |
readonly |
Type : boolean
|
Default value : false
|
Flag to set this input as read only. |
required |
Type : boolean
|
Flag to set the input as required. |
showLabel |
Type : boolean
|
Default value : true
|
Boolean flag to show label for the input fields. |
spinnerSize |
Type : "large" | "small"
|
Default value : 'large'
|
Spinner size defines the size of spinner shown in the component. Possible values are small and large. Default spinner size is large. |
textareaRows |
Type : number
|
Default value : 3
|
The property specifies the visible height of a text area, in lines. By default value is 3. |
valueClass |
Type : boolean
|
Default value : false
|
To override the default styling of input field value, set the bootstrap classes of type string. Ex: 'mb-1' |
<ng-container *ngIf="view$ | async as view">
<div [ngSwitch]="view?.metadata?.DataType | lowercase" class="form-group align-items-center" [class.d-flex]="inline"
[id]="uuid + '-container'">
<label *ngIf="showLabel" [class.m-0]="inline" [class.mr-2]="inline" class="d-inline-block mutedLabels"
[ngClass]="labelClass ? labelClass : 'font-weight-bold' ">{{(label) ? label :
view?.metadata?.DisplayName}}</label>
<i *ngIf="required && asterisk" class="fa fa-asterisk text-danger font-weight-normal custom-asterisk p-1"></i>
<!-- Picklist -->
<ng-container *ngSwitchCase="'picklist'">
<ng-select class="form-control custom picklist p-0" [searchable]="false" [(ngModel)]="value" [required]="required" [class.form-control-sm]="inputSize == 'small'"
[placeholder]="placeholder" [loading]="loading" [disabled]="readonly" (ngModelChange)="onPickChange(value)"
#picklist="ngModel" [ngClass]="{ 'is-invalid': picklist.invalid && (picklist.touched || picklist.dirty), 'font-weight-bold': valueClass && value }"
[items]="options" [multiple]="multiple" bindValue="value" bindLabel="label">
<div class="invalid-feedback">{{errorMsg}}</div>
</ng-select>
<ng-template #checkboxes>
<div *ngFor="let option of options$ | async" class="custom-control custom-radio" [class.custom-radio-sm]="inputSize == 'small'"
[class.custom-control-inline]="inline">
<input type="radio" class="custom-control-input" [name]="uuid + '_' + view?.metadata.FieldName"
[value]="option.value" [id]="uuid + '_' + view?.metadata.FieldName + '_' + option.value" [(ngModel)]="value"
(ngModelChange)="propagateChange(value)" [disabled]="readonly || option.disabled" [required]="required">
<label class="custom-control-label mr-auto"
[for]="uuid + '_' + view?.metadata.FieldName + '_' + option.value">
{{option.label}}
</label>
</div>
</ng-template>
</ng-container>
<!-- Boolean -->
<ng-container *ngSwitchCase="'boolean'">
<div *ngIf="displayFieldType === 'radio'; else booleanPicklist">
<div class="form-check">
<input type="radio" class="form-check-input" [id]="uuid + '_' + view?.metadata.FieldName + '_' + value"
[name]="uuid + '_' + view?.metadata.FieldName" [checked]="value" (change)="onBooleanChange(true)">
<label class="form-check-label" [for]="uuid + '_' + view?.metadata.FieldName + '_' + value">
{{'COMMON.YES' | translate}}
</label><br>
</div>
<div class="form-check">
<input type="radio" class="form-check-input" [id]="uuid + '_' + view?.metadata.FieldName + '_' + !value"
[name]="uuid + '_' + view?.metadata.FieldName" [checked]="!value" (change)="onBooleanChange(false)">
<label class="form-check-label" [for]="uuid + '_' + view?.metadata.FieldName + '_' + !value">
{{'COMMON.NO' | translate}}
</label><br>
</div>
</div>
<ng-template #booleanPicklist>
<select type="radio" class="form-control" [class.form-control-sm]="inputSize == 'small'" *ngSwitchCase="'boolean'"
[(ngModel)]="value" [class.custom-control-inline]="inline" (ngModelChange)="onBooleanChange(value)"
[required]="required" [disabled]="readonly">
<option *ngIf="presetBoolean" [value]="null"> {{presetBooleanLabel}} </option>
<option [value]="true"> {{'COMMON.YES' | translate}} </option>
<option [value]="false"> {{'COMMON.NO' | translate}} </option>
</select>
</ng-template>
</ng-container>
<!-- Multi select picklist -->
<ng-container *ngSwitchCase="'multipicklist'">
<div *ngIf="displayFieldType === 'dropdown'; else multiSelectCheckbox">
<ng-select class="form-control custom picklist p-0" [searchable]="false" [(ngModel)]="value" [required]="required" [class.form-control-sm]="inputSize == 'small'"
[placeholder]="placeholder" [loading]="loading" [disabled]="readonly" (ngModelChange)="onPickChange(value)"
#picklist="ngModel" [ngClass]="{ 'is-invalid': picklist.invalid && (picklist.touched || picklist.dirty) }"
[items]="options" [multiple]="true" bindValue="value" bindLabel="label">
<div class="invalid-feedback">{{errorMsg}}</div>
</ng-select>
</div>
<ng-template #multiSelectCheckbox>
<div *ngFor="let option of options" class="custom-control custom-checkbox" [class.custom-checkbox-sm]="inputSize == 'small'"
[class.custom-control-inline]="inline">
<input type="checkbox" class="custom-control-input" [checked]="value && value?.indexOf(option.value) > -1"
[id]="uuid + '_' + view?.metadata.FieldName + '_' + option.value" pattern="07[0-9]{9}"
[(ngModel)]="getsetValue(option.value).value" (ngModelChange)="onMultiChange(option.value)"
[disabled]="(enableValues?.length > 0 && enableValues?.indexOf(option.value) === -1) || readonly ? true : false"
[required]="required">
<label class="custom-control-label" [for]="uuid + '_' + view?.metadata.FieldName + '_' + option.value">
{{option.label}}
</label>
</div>
</ng-template>
</ng-container>
<!-- Number -->
<ng-container *ngSwitchCase="'double'">
<input type="number" [min]="minVal" class="form-control custom" [class.form-control-sm]="inputSize == 'small'" [id]="value"
[(ngModel)]="value" [disabled]="readonly" (ngModelChange)="propagateChange(value)" [required]="required"
[placeholder]="placeholder" #num="ngModel" step="any"
[ngClass]="{ 'is-invalid': num.invalid && (num.touched || num.dirty) || value < minVal}" />
<div class="invalid-feedback">{{errorMsg | translate}}</div>
</ng-container>
<ng-container *ngSwitchCase="'decimal'">
<input type="number" [min]="minVal" class="form-control custom" [class.form-control-sm]="inputSize == 'small'" [id]="value"
[(ngModel)]="value" [disabled]="readonly" (ngModelChange)="propagateChange(value)" [required]="required"
[placeholder]="placeholder" #num="ngModel" step="any"
[ngClass]="{ 'is-invalid': num.invalid && (num.touched || num.dirty) || value < minVal, 'font-weight-bold': valueClass }" />
<div class="invalid-feedback">{{errorMsg | translate}}</div>
</ng-container>
<ng-container *ngSwitchCase="'int'">
<input type="number" class="form-control custom" [class.form-control-sm]="inputSize == 'small'" [id]="value" [(ngModel)]="value"
[disabled]="readonly" step="1" (ngModelChange)="propagateChange(value)" [required]="required"
[placeholder]="placeholder" #num="ngModel"
[ngClass]="{ 'is-invalid': num.invalid && (num.touched || num.dirty) }" />
<div class="invalid-feedback">{{errorMsg | translate}}</div>
</ng-container>
<!-- String -->
<ng-container *ngSwitchCase="'string'">
<ng-container *ngTemplateOutlet="stringTemplate"></ng-container>
</ng-container>
<!-- Long String -->
<ng-container *ngSwitchCase="'longstring'">
<ng-container *ngTemplateOutlet="stringTemplate"></ng-container>
</ng-container>
<ng-template #stringTemplate>
<input type="text" class="form-control custom" [class.form-control-sm]="inputSize == 'small'" [id]="value" [(ngModel)]="value"
(ngModelChange)="propagateChange(value)" [disabled]="readonly" [required]="required" [placeholder]="placeholder"
#txt="ngModel"
[ngClass]="{ 'is-invalid': overrideDefaultFormValidation || txt.invalid && (txt.touched || txt.dirty) }" />
<div class="invalid-feedback">{{errorMsg | translate}}</div>
</ng-template>
<!-- Email -->
<ng-container *ngSwitchCase="'email'">
<input type="text" class="form-control custom" [class.form-control-sm]="inputSize == 'small'" [id]="value" [(ngModel)]="value"
(ngModelChange)="propagateChange(value)" [required]="required" [placeholder]="placeholder" #email="ngModel"
[ngClass]="{ 'is-invalid': email.invalid && (email.touched || email.dirty) }" />
<div class="invalid-feedback">{{errorMsg}}</div>
</ng-container>
<!-- Textarea -->
<ng-container *ngSwitchCase="'textarea'">
<textarea [(ngModel)]="value" class="form-control custom" [class.form-control-sm]="inputSize == 'small'"
(ngModelChange)="propagateChange(value)" [maxlength]="view?.metadata?.length" [rows]="textareaRows"
[required]="required" [placeholder]="placeholder"></textarea>
</ng-container>
<!-- Date -->
<div class="date-form position-relative" *ngSwitchCase="'date'">
<input type="text" [id]="uuid" class="form-control custom" bsDatepicker [class.form-control-sm]="inputSize == 'small'"
[value]="value" (bsValueChange)="onDateChange($event)" [required]="required" [placeholder]="placeholder"
[bsConfig]="{ adaptivePosition: true }">
<i class="fa fa-calendar"></i>
</div>
<!-- Datetime -->
<div class="date-form position-relative" *ngSwitchCase="'datetime'">
<input type="text" [id]="uuid" class="form-control custom" bsDatepicker [class.form-control-sm]="inputSize == 'small'"
[value]="value" (bsValueChange)="onDatetimeChange($event)" [required]="required" [placeholder]="placeholder"
[bsConfig]="{ adaptivePosition: true }">
<i class="fa fa-calendar"></i>
</div>
<!-- Percentage -->
<ng-container *ngSwitchCase="'percent'">
<input type="text" [id]="uuid" class="form-control custom" [class.form-control-sm]="inputSize == 'small'"
[ngModel]="value/100 | percent:'1.2'" (ngModelChange)="propagateChange(value)" [required]="required"
[placeholder]="placeholder">
</ng-container>
<!-- Currency -->
<ng-container *ngSwitchCase="'currency'">
<input type="number" class="form-control custom" [class.form-control-sm]="inputSize == 'small'" [id]="value" [(ngModel)]="value"
[disabled]="readonly" step=".01" (ngModelChange)="propagateChange(value)" [required]="required"
[placeholder]="placeholder" #num="ngModel"
[ngClass]="{ 'is-invalid': num.invalid && (num.touched || num.dirty) }" />
<div class="invalid-feedback">{{errorMsg}}</div>
</ng-container>
<ng-container *ngSwitchCase="'reference'">
<ng-container *ngTemplateOutlet="referenceTemplate"></ng-container>
</ng-container>
<ng-container *ngSwitchCase="'lookup'">
<ng-container *ngTemplateOutlet="referenceTemplate"></ng-container>
</ng-container>
<!-- Reference template -->
<ng-template #referenceTemplate>
<ng-select class="form-control aptSingleSelectLookup p-0" [class.form-control-sm]="inputSize == 'small'"
[class.contacts]="lookupOptions?.secondaryTextField" [(ngModel)]="lookupId" [items]="view?.lookupResults"
(search)="onLookupSearch($event)" [required]="required" [bindLabel]="lookupOptions?.primaryTextField"
bindValue="Id" [placeholder]="placeholder" [loading]="loading"
(ngModelChange)="onLookupChange($event, view?.lookupResults)" #select="ngModel"
[ngClass]="{ 'is-invalid': select.invalid && (select.touched || select.dirty) }" [disabled]="readonly"
[clearable]="allowClearableLookups" (clear)="setLookupFieldData()" (focus)="setLookupFieldData()">
<ng-template ng-option-tmp let-item="item" let-index="index" let-search="searchTerm">
<span *ngIf="!lookupOptions?.secondaryTextField" class="basicOption" [ngOptionHighlight]="search">
{{item[lookupOptions?.primaryTextField]}}
</span>
<div *ngIf="lookupOptions?.secondaryTextField" class="d-flex align-items-center contactOption">
<img *ngIf="lookupOptions?.thumbnailField" class="rounded-circle mr-4" width="32" height="32"
src="./assets/images/default.png" alt="Contact Image">
<div class="d-flex flex-column h-100 justify-content-around">
<span [ngOptionHighlight]="search">{{item[lookupOptions?.primaryTextField]}}</span>
<i class="small" *ngIf="lookupOptions?.secondaryTextField">{{item[lookupOptions?.secondaryTextField]}}</i>
</div>
</div>
</ng-template>
<ng-template ng-loadingspinner-tmp>
<apt-spinner [large]="spinnerSize === 'large'"></apt-spinner>
</ng-template>
</ng-select>
<div class="invalid-feedback">{{errorMsg}}</div>
</ng-template>
<!-- Address -->
<ng-container *ngSwitchCase="'address'">
<apt-address [(ngModel)]="value"></apt-address>
</ng-container>
</div>
</ng-container>
./input-field.component.scss
apt-input-field {
display: block;
.custom-asterisk {
font-size: 8px;
}
.form-control.is-invalid {
padding-right: 0rem !important;
background-size: 0%;
}
select {
text-indent: 5px;
}
.date-form {
input[bsdatepicker] {
padding-right: 1.6rem;
}
i {
position: absolute;
top: 25%;
right: 3%;
}
}
.ng-select.picklist {
.ng-select-container {
height: 100%;
min-height: 100%;
}
}
.ng-select .ng-select-container {
border: none
}
ng-select.aptSingleSelectLookup {
&.ng-select-focused:not(.ng-select-opened):not(.ng-invalid)>.ng-select-container {
border: 1.4px solid rgba(0, 36, 163, 1) !important;
box-shadow: none !important;
}
.ng-select-container {
background-color: transparent;
min-height: 34px;
height: 34px;
border-width: 0px;
.ng-arrow-wrapper {
display: none;
}
apt-spinner {
svg {
width: 18px;
height: 18px;
}
}
.ng-clear-wrapper {
padding-top: 0rem !important;
padding-left: 0rem !important;
width: 24px;
height: 24px;
&:hover .ng-clear {
opacity: 1;
}
.ng-clear {
width: 24px;
height: 24px;
color: transparent;
content: "";
background-image: url("data:image/svg+xml,%3Csvg fill='%23000' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='0 0 24 24' class='ng-scope'%3E%3Cpolygon points='20 5.611 18.389 4 12 10.389 5.611 4 4 5.611 10.389 12 4 18.389 5.611 20 12 13.611 18.389 20 20 18.389 13.611 12'%3E%3C/polygon%3E%3C/svg%3E");
opacity: 0.5;
}
}
&::before {
width: 24px;
height: 24px;
content: "";
background-image: url("data:image/svg+xml,%3Csvg fill='%23000' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='0 0 24 24' class='ng-scope'%3E%3Cpath d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'%3E%3C/path%3E%3C/svg%3E");
}
}
&.ng-select-single .ng-select-container .ng-value-container .ng-input {
padding-left: 34px;
padding-right: 36px;
&>input {
cursor: text;
}
}
&.contacts {
.ng-dropdown-panel {
bottom: auto !important;
}
}
.ng-dropdown-panel {
.ng-dropdown-header {
font-size: 12px;
padding-left: 14px;
border: none;
}
.ng-dropdown-panel-items {
.ng-option {
min-height: 40px;
padding: 4px 10px 4px 14px;
.basicOption {
line-height: 32px;
}
.contactOption {
height: 56px;
}
}
}
}
}
.ng-select .ng-clear-wrapper {
padding-top: 0.3125rem !important;
padding-left: 0.3125rem !important;
}
}