ddata-ui-input
Version:
DData UI Input module, components, models & services
823 lines (807 loc) • 150 kB
JavaScript
import { faCog, faCheckSquare, faSquare, faCalendar, faSearch } from '@fortawesome/free-solid-svg-icons';
import { BaseModel, DdataCoreModule, ValidatorService, ProxyFactoryService, Paginate, SpinnerService } from 'ddata-core';
import * as i0 from '@angular/core';
import { Pipe, EventEmitter, Input, Output, ChangeDetectionStrategy, Component, ViewChild, HostListener, ViewContainerRef, signal, NgModule } from '@angular/core';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i2 from '@fortawesome/angular-fontawesome';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import * as i2$1 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import * as i4 from 'ngx-color-picker';
import { ColorPickerComponent, ColorPickerDirective } from 'ngx-color-picker';
import * as moment from 'moment';
import * as i3 from '@ng-bootstrap/ng-bootstrap';
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
import { BehaviorSubject, fromEvent, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, takeUntil, tap, switchMap, map, finalize, take } from 'rxjs/operators';
import * as i1$1 from '@angular/router';
import * as i2$2 from 'ddata-ui-common';
import { DdataUiCommonModule } from 'ddata-ui-common';
import * as i3$1 from 'ngx-material-timepicker';
import { NgxMaterialTimepickerModule } from 'ngx-material-timepicker';
class DialogContentItem {
constructor(component, data) {
this.component = component;
this.data = data;
}
}
class DialogContentWithOptions {
constructor(component, options) {
this.component = component;
this.options = options;
}
}
// tslint:disable: variable-name
class SearchModelFunctions extends BaseModel {
constructor() {
super(...arguments);
this.icons = {
cog: faCog
};
}
init(data) {
const searchData = !!data ? data : {};
this.initAsNumberWithDefaults(['id'], searchData);
this.initAsStringWithDefaults(['name', 'description', 'type', 'found_model_name'], searchData);
this.icon = this.setIcon(this.type);
this.url = this.setUrl(this.type);
return this;
}
setUrl(type) {
return type.replace(new RegExp(/_/, 'g'), '/');
}
setIcon(type) {
if (!type) {
return this.icons.cog;
}
return this.icons[type] ?? this.icons.cog;
}
}
class SearchAbstract extends SearchModelFunctions {
constructor() {
super(...arguments);
// tslint:disable: variable-name
this.api_endpoint = '/search';
this.model_name = 'Search';
}
init(data) {
const searchData = !!data ? data : {};
super.init(searchData);
this.initAsStringWithDefaults(['searchText'], searchData);
return this;
}
prepareToSave() {
return {
term: !!this.searchText ? this.searchText : ''
};
}
}
class SearchResultAbstract extends SearchModelFunctions {
init(data) {
super.init(data);
return this;
}
}
class DescriptionPipe {
transform(value) {
const transformValue = !!value ? value : '';
let result = '';
const parts = transformValue.split('|');
parts.forEach((part) => {
let processedPart = part.replace(new RegExp(/^tel:(.*?)$/), '<a href="tel:$1" class="mr-3">$1</a>');
processedPart = processedPart.replace(new RegExp(/^email:(.*?)$/), '<a href="mailto:$1" class="mr-3">$1</a>');
processedPart = processedPart.replace(new RegExp(/^url:(.*?)$/), '<a href="$1" class="mr-3" target="_blank">$1</a>');
processedPart = processedPart.replace(new RegExp(/^description:(.*?)$/), '<span class="description">$1</span>');
result += `${processedPart} `;
});
return result;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DescriptionPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.0.6", ngImport: i0, type: DescriptionPipe, isStandalone: false, name: "description" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DescriptionPipe, decorators: [{
type: Pipe,
args: [{
name: 'description',
standalone: false
}]
}] });
class InputHelperService {
constructor() {
this.validatorService = DdataCoreModule.InjectorInstance.get(ValidatorService);
}
validateField(model, field) {
// handle missing validation rule
if (!model.validationRules[field]) {
console.error(`Missing validation rule:${field} from model: ${model.constructor.name}`);
return false;
}
const isValid = this.validatorService.validate(model[field], model.validationRules[field]);
// if not valid & validation error is not set
if (!isValid && !model.validationErrors.includes(field)) {
model.validationErrors.push(field);
return false;
}
// it's valid & validation error set - need remove
if (model.validationErrors.includes(field)) {
model.validationErrors.splice(model.validationErrors.indexOf(field), 1);
}
return true;
}
getTitle(model, field) {
if (!model || !model.fields[field] || !model.fields[field].title) {
console.error(`The model not contains the '${field}' field's title. You need to set in your model the fields.${field}.title field.`);
return '';
}
return model.fields[field].title;
}
getLabel(model, field) {
if (!model || !model.fields[field] || !model.fields[field].label) {
console.error(`The model not contains the '${field}' field's label. You need to set in your model the fields.${field}.label field.`);
return '';
}
return model.fields[field].label;
}
getPlaceholder(model, field) {
if (!model || !model.fields[field] || !model.fields[field].placeholder) {
console.error(`The model not contains the '${field}' field's placeholder. You need to set in your model the fields.${field}.placeholder field.`);
return '';
}
return model.fields[field].title;
}
getPrepend(model, field) {
if (!model || !model.fields[field] || !model.fields[field].prepend) {
return '';
}
return model.fields[field].prepend;
}
getAppend(model, field) {
if (!model || !model.fields[field] || !model.fields[field].append) {
return '';
}
return model.fields[field].append;
}
isRequired(model, field) {
try {
// Check if model and validationRules exist
if (!model || !model.validationRules || !model.validationRules[field]) {
return false;
}
const rules = model.validationRules[field];
// According to ValidationRuleInterface, rules should be Array<Rule>
if (Array.isArray(rules)) {
return rules.includes('required');
}
// Fallback: Handle object format for compatibility (though this shouldn't be the standard)
if (typeof rules === 'object' && rules !== null) {
// Object format: { required: true }
return Boolean(rules.required);
}
// String format: 'required'
if (typeof rules === 'string') {
return rules === 'required';
}
// Boolean format: true (means required)
if (typeof rules === 'boolean') {
return rules;
}
return false;
}
catch {
return false;
}
}
randChars() {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
for (let i = 0; i < 50; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
}
class DdataInputCheckboxComponent {
set model(value) {
let actualValue = value;
if (!actualValue) {
actualValue = new BaseModel();
}
this._model = actualValue;
if (!!this._model.fields) {
if (!!this._model.fields[this._field]) {
this._label = this._model.fields[this._field].label ?? '';
}
}
}
get model() {
return this._model;
}
set field(fieldValue) {
let actualValue = fieldValue;
if (actualValue === 'undefined') {
actualValue = 'isValid';
}
this._field = actualValue;
}
get field() {
return this._field;
}
constructor() {
// Input properties
this.disabled = false;
this.showLabel = true;
this.showLabelAfter = true;
this.labelClass = 'col pl-2 col-form-label';
this.wrapperClass = 'd-flex';
this.iconOn = faCheckSquare;
this.iconOff = faSquare;
// Output properties
this.changed = new EventEmitter();
// tslint:disable: variable-name
this._model = new BaseModel();
this._field = 'isValid';
this._label = '';
this.iterable = 0;
}
ngOnInit() {
this.iterable = Math.floor(Math.random() * 100);
}
clicked() {
if (!this.disabled) {
this.model[this._field] = !this.model[this._field];
this.changed.emit(this.model[this._field]);
}
}
getIcon() {
return !!this.model[this._field] ? this.iconOn : this.iconOff;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DdataInputCheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.6", type: DdataInputCheckboxComponent, isStandalone: false, selector: "dd-input-checkbox", inputs: { disabled: "disabled", showLabel: "showLabel", showLabelAfter: "showLabelAfter", labelClass: "labelClass", wrapperClass: "wrapperClass", iconOn: "iconOn", iconOff: "iconOff", model: "model", field: "field" }, outputs: { changed: "changed" }, ngImport: i0, template: "<div [class]=\"wrapperClass\">\n <label\n *ngIf=\"showLabel && !showLabelAfter\"\n [class]=\"labelClass\"\n [class.disabled]=\"disabled\"\n [for]=\"_field + iterable\"\n >\n {{ _label }}:\n </label>\n\n <button\n type=\"button\"\n class=\"btn btn-light\"\n (click)=\"clicked()\"\n [disabled]=\"disabled\"\n [id]=\"_field + iterable\"\n [name]=\"_field + iterable\"\n [title]=\"_label\"\n >\n <fa-icon [icon]=\"getIcon()\"></fa-icon>\n </button>\n\n <label\n *ngIf=\"showLabel && showLabelAfter\"\n [class]=\"labelClass\"\n [class.disabled]=\"disabled\"\n [for]=\"_field + iterable\"\n >\n {{ _label }}\n </label>\n</div>\n", styles: [".disabled{opacity:.3}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DdataInputCheckboxComponent, decorators: [{
type: Component,
args: [{ selector: 'dd-input-checkbox', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div [class]=\"wrapperClass\">\n <label\n *ngIf=\"showLabel && !showLabelAfter\"\n [class]=\"labelClass\"\n [class.disabled]=\"disabled\"\n [for]=\"_field + iterable\"\n >\n {{ _label }}:\n </label>\n\n <button\n type=\"button\"\n class=\"btn btn-light\"\n (click)=\"clicked()\"\n [disabled]=\"disabled\"\n [id]=\"_field + iterable\"\n [name]=\"_field + iterable\"\n [title]=\"_label\"\n >\n <fa-icon [icon]=\"getIcon()\"></fa-icon>\n </button>\n\n <label\n *ngIf=\"showLabel && showLabelAfter\"\n [class]=\"labelClass\"\n [class.disabled]=\"disabled\"\n [for]=\"_field + iterable\"\n >\n {{ _label }}\n </label>\n</div>\n", styles: [".disabled{opacity:.3}\n"] }]
}], ctorParameters: () => [], propDecorators: { disabled: [{
type: Input
}], showLabel: [{
type: Input
}], showLabelAfter: [{
type: Input
}], labelClass: [{
type: Input
}], wrapperClass: [{
type: Input
}], iconOn: [{
type: Input
}], iconOff: [{
type: Input
}], changed: [{
type: Output
}], model: [{
type: Input
}], field: [{
type: Input
}] } });
class DdataInputColorComponent {
set model(value) {
let modelValue = value;
if (!modelValue) {
modelValue = new BaseModel();
}
this._model = modelValue;
if (!!this._model && !!this._model.fields[this._field]) {
this._title = this.helperService.getTitle(this._model, this._field);
this._placeholder = this.helperService.getPlaceholder(this._model, this._field);
this._prepend = this.helperService.getPrepend(this._model, this._field);
this._append = this.helperService.getAppend(this._model, this._field);
this._label = this.helperService.getLabel(this._model, this._field);
}
if (!!this._model && !!this._model.validationRules[this._field]) {
this._isRequired = this.helperService.isRequired(this._model, this._field);
}
}
get model() {
return this._model;
}
set field(value) {
let fieldValue = value;
if (fieldValue === 'undefined') {
fieldValue = 'isValid';
}
this._field = fieldValue;
}
set append(value) {
let appendValue = value;
if (appendValue === 'undefined') {
appendValue = '';
}
this._append = appendValue;
}
set prepend(value) {
let prependValue = value;
if (prependValue === 'undefined') {
prependValue = '';
}
this._prepend = prependValue;
}
set labelText(value) {
let labelValue = value;
if (labelValue === 'undefined') {
labelValue = '';
}
this._label = labelValue;
}
constructor(helperService) {
this.helperService = helperService;
this.disabled = false;
this.type = 'text';
this.inputClass = 'form-control';
this.labelClass = 'col-12 col-md-3 px-0 col-form-label';
this.inputBlockClass = 'col-12 d-flex px-0';
this.inputBlockExtraClass = 'col-md-9';
this.showLabel = true;
this.autoFocus = false;
this.wrapperClass = 'd-flex flex-wrap';
this.changed = new EventEmitter();
// tslint:disable: variable-name
this._field = '';
this._title = '';
this._label = '';
this._placeholder = '';
this._prepend = '';
this._append = '';
this._isRequired = false;
this._model = new BaseModel();
this.random = this.helperService.randChars();
this.toggle = false;
this.validatorService = DdataCoreModule.InjectorInstance.get(ValidatorService);
}
ngOnInit() {
if (this.autoFocus) {
this.inputBox.nativeElement.focus();
}
}
validateField() {
const isValid = this.helperService.validateField(this._model, this._field);
if (isValid) {
this.changed.emit(this._model);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DdataInputColorComponent, deps: [{ token: InputHelperService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.6", type: DdataInputColorComponent, isStandalone: false, selector: "dd-input-color", inputs: { disabled: "disabled", type: "type", inputClass: "inputClass", labelClass: "labelClass", inputBlockClass: "inputBlockClass", inputBlockExtraClass: "inputBlockExtraClass", showLabel: "showLabel", autoFocus: "autoFocus", wrapperClass: "wrapperClass", model: "model", field: "field", append: "append", prepend: "prepend", labelText: "labelText" }, outputs: { changed: "changed" }, viewQueries: [{ propertyName: "inputBox", first: true, predicate: ["inputBox"], descendants: true }], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_isRequired\"> *</span>\n </label>\n\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div\n class=\"input-color-container\"\n [style.background]=\"model[_field]\"\n (click)=\"toggle = !toggle\"\n ></div>\n\n <div class=\"input-group-prepend\" *ngIf=\"_prepend !== ''\">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [(ngModel)]=\"model[_field]\"\n [id]=\"_field + '_' + random\"\n [attr.name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [disabled]=\"disabled\"\n [type]=\"type\"\n [(colorPicker)]=\"model[_field]\"\n [(cpToggle)]=\"toggle\"\n cpPosition=\"bottom\"\n cpOutputFormat=\"hex\"\n cpAlphaChannel=\"disabled\"\n cpFallbackColor=\"#c0c0c0\"\n (keyup)=\"validateField()\"\n #inputBox\n />\n\n <div class=\"input-group-append\" *ngIf=\"_append !== ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n</div>\n", styles: [".input-color-container{width:40px}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i4.ColorPickerDirective, selector: "[colorPicker]", inputs: ["colorPicker", "cpWidth", "cpHeight", "cpToggle", "cpDisabled", "cpIgnoredElements", "cpFallbackColor", "cpColorMode", "cpCmykEnabled", "cpOutputFormat", "cpAlphaChannel", "cpDisableInput", "cpDialogDisplay", "cpSaveClickOutside", "cpCloseClickOutside", "cpUseRootViewContainer", "cpPosition", "cpPositionOffset", "cpPositionRelativeToArrow", "cpOKButton", "cpOKButtonText", "cpOKButtonClass", "cpCancelButton", "cpCancelButtonText", "cpCancelButtonClass", "cpEyeDropper", "cpPresetLabel", "cpPresetColors", "cpPresetColorsClass", "cpMaxPresetColorsLength", "cpPresetEmptyMessage", "cpPresetEmptyMessageClass", "cpAddColorButton", "cpAddColorButtonText", "cpAddColorButtonClass", "cpRemoveColorButtonClass", "cpArrowPosition", "cpExtraTemplate"], outputs: ["cpInputChange", "cpToggleChange", "cpSliderChange", "cpSliderDragEnd", "cpSliderDragStart", "colorPickerOpen", "colorPickerClose", "colorPickerCancel", "colorPickerSelect", "colorPickerChange", "cpCmykColorChange", "cpPresetColorsChange"], exportAs: ["ngxColorPicker"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DdataInputColorComponent, decorators: [{
type: Component,
args: [{ selector: 'dd-input-color', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_isRequired\"> *</span>\n </label>\n\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div\n class=\"input-color-container\"\n [style.background]=\"model[_field]\"\n (click)=\"toggle = !toggle\"\n ></div>\n\n <div class=\"input-group-prepend\" *ngIf=\"_prepend !== ''\">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [(ngModel)]=\"model[_field]\"\n [id]=\"_field + '_' + random\"\n [attr.name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [disabled]=\"disabled\"\n [type]=\"type\"\n [(colorPicker)]=\"model[_field]\"\n [(cpToggle)]=\"toggle\"\n cpPosition=\"bottom\"\n cpOutputFormat=\"hex\"\n cpAlphaChannel=\"disabled\"\n cpFallbackColor=\"#c0c0c0\"\n (keyup)=\"validateField()\"\n #inputBox\n />\n\n <div class=\"input-group-append\" *ngIf=\"_append !== ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n</div>\n", styles: [".input-color-container{width:40px}\n"] }]
}], ctorParameters: () => [{ type: InputHelperService }], propDecorators: { disabled: [{
type: Input
}], type: [{
type: Input
}], inputClass: [{
type: Input
}], labelClass: [{
type: Input
}], inputBlockClass: [{
type: Input
}], inputBlockExtraClass: [{
type: Input
}], showLabel: [{
type: Input
}], autoFocus: [{
type: Input
}], wrapperClass: [{
type: Input
}], changed: [{
type: Output
}], inputBox: [{
type: ViewChild,
args: ['inputBox']
}], model: [{
type: Input
}], field: [{
type: Input
}], append: [{
type: Input
}], prepend: [{
type: Input
}], labelText: [{
type: Input
}] } });
class DdataInputDateComponent {
set moment(value) {
let momentValue = value;
if (!momentValue) {
momentValue = moment;
}
this._moment = momentValue;
}
set model(value) {
let modelValue = value;
if (!modelValue) {
modelValue = new BaseModel();
}
this._model = modelValue;
if (!!this._model && !!this._model.fields[this._field]) {
this._title = this.helperService.getTitle(this._model, this._field);
this._placeholder = this.helperService.getPlaceholder(this._model, this._field);
this._prepend = this.helperService.getPrepend(this._model, this._field);
this._append = this.helperService.getAppend(this._model, this._field);
this._label = this.helperService.getLabel(this._model, this._field);
}
if (!!this._model && !!this._model.validationRules[this._field]) {
this._isRequired = this.helperService.isRequired(this._model, this._field);
}
}
get model() {
return this._model;
}
set field(value) {
let fieldValue = value;
if (fieldValue === 'undefined') {
fieldValue = 'isValid';
}
this._field = fieldValue;
}
set append(value) {
let appendValue = value;
if (appendValue === 'undefined') {
appendValue = '';
}
this._append = appendValue;
}
set prepend(value) {
let prependValue = value;
if (prependValue === 'undefined') {
prependValue = '';
}
this._prepend = prependValue;
}
set labelText(value) {
let labelValue = value;
if (labelValue === 'undefined') {
labelValue = '';
}
this._label = labelValue;
}
constructor(changeDetector) {
this.changeDetector = changeDetector;
this.disabled = false;
this.inputClass = 'form-control';
this.labelClass = 'col-12 col-md-3 px-0 col-form-label';
this.inputBlockClass = 'col-12 d-flex px-0';
this.inputBlockExtraClass = 'col-md-9';
this.showLabel = true;
this.autoFocus = false;
this.isViewOnly = false;
this.viewOnlyClass = 'form-control border-0 bg-light';
this.buttonClass = 'input-group-prepend btn btn-light mb-0';
this.wrapperClass = 'd-flex flex-wrap';
this.format = 'YYYY-MM-DD';
this.separator = '-';
this.labelApply = 'OK';
this.labelCancel = 'Cancel';
this.position = 'center';
this.direction = 'down';
this.showIcon = true;
this.autoApply = true;
this.singleDatePicker = true;
this.changed = new EventEmitter();
this.helperService = DdataCoreModule.InjectorInstance.get(InputHelperService);
// tslint:disable: variable-name
this._field = '';
this._title = '';
this._label = '';
this._placeholder = '';
this._prepend = '';
this._append = '';
this._isRequired = false;
this._model = new BaseModel();
this._moment = moment;
this.icon = {
calendar: faCalendar
};
this.random = this.helperService.randChars();
this.selectedValue = !!this.model[this._field] ? this.model[this._field] : '';
}
ngOnInit() {
if (!!this.model[this._field]) {
this.selectedValue = this.model[this._field];
}
if (this.autoFocus) {
this.inputBox.nativeElement.focus();
}
}
change(value) {
this.selectedValue = `${value.year}-${value.month.toString().padStart(2, '0')}-${value.day
.toString()
.padStart(2, '0')}`;
this.model[this._field] = this.selectedValue;
const isValid = this.helperService.validateField(this._model, this._field);
if (isValid) {
this.changed.emit(this._model);
}
}
typeChange(event) {
this._model[this._field] = event.target.value;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DdataInputDateComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.6", type: DdataInputDateComponent, isStandalone: false, selector: "dd-input-date", inputs: { disabled: "disabled", inputClass: "inputClass", labelClass: "labelClass", inputBlockClass: "inputBlockClass", inputBlockExtraClass: "inputBlockExtraClass", showLabel: "showLabel", autoFocus: "autoFocus", isViewOnly: "isViewOnly", viewOnlyClass: "viewOnlyClass", buttonClass: "buttonClass", wrapperClass: "wrapperClass", format: "format", separator: "separator", labelApply: "labelApply", labelCancel: "labelCancel", position: "position", direction: "direction", showIcon: "showIcon", autoApply: "autoApply", singleDatePicker: "singleDatePicker", moment: "moment", model: "model", field: "field", append: "append", prepend: "prepend", labelText: "labelText" }, outputs: { changed: "changed" }, viewQueries: [{ propertyName: "inputBox", first: true, predicate: ["inputBox"], descendants: true }], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_is_required\"> *</span>\n </label>\n\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div class=\"input-group-prepend\" *ngIf=\"_prepend !== ''\">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <ng-container *ngIf=\"!isViewOnly\">\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [disabled]=\"disabled\"\n [id]=\"_field + '_' + random\"\n [name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [value]=\"model[_field]\"\n (dateSelect)=\"change($event)\"\n type=\"text\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n (click)=\"d.toggle()\"\n (change)=\"typeChange($event)\"\n />\n </ng-container>\n\n <ng-container *ngIf=\"isViewOnly\">\n <div [class]=\"viewOnlyClass\">{{ model[_field] }}</div>\n </ng-container>\n\n <label [class]=\"buttonClass\" *ngIf=\"!disabled && showIcon\" [for]=\"_field + '_' + random\">\n <fa-icon [icon]=\"icon.calendar\"></fa-icon>\n </label>\n\n <div class=\"input-group-append\" *ngIf=\"_append !== ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n</div>\n", styles: [":host{position:relative;flex:1 1 auto}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }, { kind: "directive", type: i3.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DdataInputDateComponent, decorators: [{
type: Component,
args: [{ selector: 'dd-input-date', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_is_required\"> *</span>\n </label>\n\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div class=\"input-group-prepend\" *ngIf=\"_prepend !== ''\">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <ng-container *ngIf=\"!isViewOnly\">\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [disabled]=\"disabled\"\n [id]=\"_field + '_' + random\"\n [name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [value]=\"model[_field]\"\n (dateSelect)=\"change($event)\"\n type=\"text\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n (click)=\"d.toggle()\"\n (change)=\"typeChange($event)\"\n />\n </ng-container>\n\n <ng-container *ngIf=\"isViewOnly\">\n <div [class]=\"viewOnlyClass\">{{ model[_field] }}</div>\n </ng-container>\n\n <label [class]=\"buttonClass\" *ngIf=\"!disabled && showIcon\" [for]=\"_field + '_' + random\">\n <fa-icon [icon]=\"icon.calendar\"></fa-icon>\n </label>\n\n <div class=\"input-group-append\" *ngIf=\"_append !== ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n</div>\n", styles: [":host{position:relative;flex:1 1 auto}\n"] }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { disabled: [{
type: Input
}], inputClass: [{
type: Input
}], labelClass: [{
type: Input
}], inputBlockClass: [{
type: Input
}], inputBlockExtraClass: [{
type: Input
}], showLabel: [{
type: Input
}], autoFocus: [{
type: Input
}], isViewOnly: [{
type: Input
}], viewOnlyClass: [{
type: Input
}], buttonClass: [{
type: Input
}], wrapperClass: [{
type: Input
}], format: [{
type: Input
}], separator: [{
type: Input
}], labelApply: [{
type: Input
}], labelCancel: [{
type: Input
}], position: [{
type: Input
}], direction: [{
type: Input
}], showIcon: [{
type: Input
}], autoApply: [{
type: Input
}], singleDatePicker: [{
type: Input
}], changed: [{
type: Output
}], inputBox: [{
type: ViewChild,
args: ['inputBox']
}], moment: [{
type: Input
}], model: [{
type: Input
}], field: [{
type: Input
}], append: [{
type: Input
}], prepend: [{
type: Input
}], labelText: [{
type: Input
}] } });
class DdataInputComponent {
set model(value) {
// prevent undefined
if (!value) {
console.error('The input-box component get undefined model');
return;
}
this._model = value;
if (!this._model.fields) {
console.error(`Your ${this._model.model_name}'s 'fields' field is`, this._model.fields);
return;
}
if (!this._model.fields[this._field]) {
console.error(`The ${this._model.model_name}'s ${this._field} field is `, this._model.fields[this._field]);
return;
}
if (!!this._model && !!this._model.fields[this._field]) {
this._title = this.helperService.getTitle(this._model, this._field);
this._placeholder = this.helperService.getPlaceholder(this._model, this._field);
this._prepend = this.helperService.getPrepend(this._model, this._field);
this._append = this.helperService.getAppend(this._model, this._field);
this._label = this.helperService.getLabel(this._model, this._field);
}
if (!!this._model && !!this._model.validationRules[this._field]) {
this._isRequired = this.helperService.isRequired(this._model, this._field);
}
}
get model() {
return this._model;
}
set field(fieldValue) {
let actualValue = fieldValue;
if (actualValue === 'undefined') {
actualValue = 'isValid';
}
this._field = actualValue;
}
set append(appendValue) {
let actualValue = appendValue;
if (actualValue === 'undefined') {
actualValue = '';
}
this._append = actualValue;
}
set prepend(prependValue) {
let actualValue = prependValue;
if (actualValue === 'undefined') {
actualValue = '';
}
this._prepend = actualValue;
}
set labelText(labelValue) {
let actualValue = labelValue;
if (actualValue === 'undefined') {
actualValue = '';
}
this._label = actualValue;
}
constructor() {
// Input properties
this.disabled = false;
this.isViewOnly = false;
this.type = 'text';
this.inputClass = 'form-control';
this.labelClass = 'col-12 col-md-3 px-0 col-form-label';
this.inputBlockClass = 'col-12 d-flex px-0';
this.inputBlockExtraClass = 'col-md-9';
this.viewOnlyClass = 'form-control border-0 bg-light';
this.wrapperClass = 'd-flex flex-wrap';
this.showLabel = true;
this.autoFocus = false;
this.enableCharacterCounter = false;
this.enableWordCounter = false;
this.maxLength = 255;
this.maxWords = 7;
this.wordCounterWarningMessage = '';
// Output properties
this.changed = new EventEmitter();
this.maxLengthReached = new EventEmitter();
// Private properties
this.helperService = DdataCoreModule.InjectorInstance.get(InputHelperService);
// tslint:disable: variable-name
this._field = '';
this._title = '';
this._label = '';
this._placeholder = '';
this._prepend = '';
this._append = '';
this._max = '';
this._isRequired = false;
this._model = new BaseModel();
this.random = this.helperService.randChars();
this.displayWordCounterWarning = false;
}
ngAfterViewInit() {
if (this.autoFocus) {
this.inputBox.nativeElement.focus();
}
}
validateField() {
const isValid = this.helperService.validateField(this._model, this._field);
if (isValid) {
this.changed.emit(this._model);
}
}
setWordCounterWarning(value) {
this.displayWordCounterWarning = value;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DdataInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.6", type: DdataInputComponent, isStandalone: false, selector: "dd-input", inputs: { disabled: "disabled", isViewOnly: "isViewOnly", type: "type", inputClass: "inputClass", labelClass: "labelClass", inputBlockClass: "inputBlockClass", inputBlockExtraClass: "inputBlockExtraClass", viewOnlyClass: "viewOnlyClass", wrapperClass: "wrapperClass", showLabel: "showLabel", autoFocus: "autoFocus", enableCharacterCounter: "enableCharacterCounter", enableWordCounter: "enableWordCounter", maxLength: "maxLength", maxWords: "maxWords", wordCounterWarningMessage: "wordCounterWarningMessage", model: "model", field: "field", append: "append", prepend: "prepend", labelText: "labelText" }, outputs: { changed: "changed", maxLengthReached: "maxLengthReached" }, viewQueries: [{ propertyName: "inputBox", first: true, predicate: ["inputBox"], descendants: true }], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_isRequired\"> *</span>\n </label>\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div class=\"input-group-prepend\" *ngIf=\"_prepend !== ''\">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <ng-container *ngIf=\"!isViewOnly\">\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [(ngModel)]=\"model[_field]\"\n [id]=\"_field + '_' + random\"\n [attr.name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [disabled]=\"disabled\"\n [type]=\"type\"\n [autocomplete]=\"random\"\n (keyup)=\"validateField()\"\n #inputBox\n />\n <ng-container *ngIf=\"enableCharacterCounter\">\n <dd-character-counter\n [currentLength]=\"model[_field]?.length || 0\"\n [maxLength]=\"maxLength\"\n ></dd-character-counter>\n </ng-container>\n <ng-container *ngIf=\"enableWordCounter\">\n <dd-word-counter\n [currentLength]=\"model[_field]\"\n [maxLength]=\"maxWords\"\n (maxLentghReached)=\"showWordCounterWarning = $event\"\n ></dd-word-counter>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"isViewOnly\">\n <div\n [id]=\"_field + '_' + random\"\n [class]=\"viewOnlyClass\"\n [attr.name]=\"_field + '_' + random\"\n [title]=\"_title\"\n >\n {{ model[_field] }}\n </div>\n </ng-container>\n <div class=\"input-group-append\" *ngIf=\"_append !== ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n <div *ngIf=\"displayWordCounterWarning && wordCounterWarningMessage !== ''\" class=\"d-flex pb-2\">\n <div class=\"col-12 col-md-7 offset-md-3 bg-warning p-2 rounded\">\n {{ wordCounterWarningMessage }}\n </div>\n </div>\n</div>\n", styles: [".autocomplete-list-container{position:absolute;display:inline-block;top:100%;width:100%;transition:all .2s}.autocomplete-spinner-place{top:calc(100% + 40px);transition:all .2s}.autocomplete-list{position:absolute;border:1px solid #d4d4d4;border-bottom:none;border-top:none;z-index:99;top:100%;left:0;right:0;box-shadow:0 5px 10px #0000004d}.autocomplete-list-item{padding:10px;cursor:pointer;background-color:#fff;border-bottom:1px solid #d4d4d4}.autocomplete-list-item:hover{background-color:#e9e9e9}.active{background-color:#1e90ff!important;color:#fff}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DdataInputComponent, decorators: [{
type: Component,
args: [{ selector: 'dd-input', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div [class]=\"wrapperClass\">\n <label [class]=\"labelClass\" [for]=\"_field + '_' + random\" *ngIf=\"showLabel\">\n {{ _label }}:\n <span *ngIf=\"_isRequired\"> *</span>\n </label>\n <div [class]=\"inputBlockClass\" [ngClass]=\"showLabel ? inputBlockExtraClass : ''\">\n <div class=\"input-group-prepend\" *ngIf=\"_prepend !== ''\">\n <div class=\"input-group-text\">{{ _prepend }}</div>\n </div>\n\n <ng-container *ngIf=\"!isViewOnly\">\n <input\n [class.invalid]=\"model.validationErrors.includes(_field)\"\n [class]=\"inputClass\"\n [(ngModel)]=\"model[_field]\"\n [id]=\"_field + '_' + random\"\n [attr.name]=\"_field + '_' + random\"\n [placeholder]=\"_placeholder\"\n [title]=\"_title\"\n [disabled]=\"disabled\"\n [type]=\"type\"\n [autocomplete]=\"random\"\n (keyup)=\"validateField()\"\n #inputBox\n />\n <ng-container *ngIf=\"enableCharacterCounter\">\n <dd-character-counter\n [currentLength]=\"model[_field]?.length || 0\"\n [maxLength]=\"maxLength\"\n ></dd-character-counter>\n </ng-container>\n <ng-container *ngIf=\"enableWordCounter\">\n <dd-word-counter\n [currentLength]=\"model[_field]\"\n [maxLength]=\"maxWords\"\n (maxLentghReached)=\"showWordCounterWarning = $event\"\n ></dd-word-counter>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"isViewOnly\">\n <div\n [id]=\"_field + '_' + random\"\n [class]=\"viewOnlyClass\"\n [attr.name]=\"_field + '_' + random\"\n [title]=\"_title\"\n >\n {{ model[_field] }}\n </div>\n </ng-container>\n <div class=\"input-group-append\" *ngIf=\"_append !== ''\">\n <div class=\"input-group-text\">{{ _append }}</div>\n </div>\n </div>\n <div *ngIf=\"displayWordCounterWarning && wordCounterWarningMessage !== ''\" class=\"d-flex pb-2\">\n <div class=\"col-12 col-md-7 offset-md-3 bg-warning p-2 rounded\">\n {{ wordCounterWarningMessage }}\n </div>\n </div>\n</div>\n", styles: [".autocomplete-list-container{position:absolute;display:inline-block;top:100%;width:100%;transition:all .2s}.autocomplete-spinner-place{top:calc(100% + 40px);transition:all .2s}.autocomplete-list{position:absolute;border:1px solid #d4d4d4;border-bottom:none;border-top:none;z-index:99;top:100%;left:0;right:0;box-shadow:0 5px 10px #0000004d}.autocomplete-list-item{padding:10px;cursor:pointer;background-color:#fff;border-bottom:1px solid #d4d4d4}.autocomplete-list-item:hover{background-color:#e9e9e9}.active{background-color:#1e90ff!important;color:#fff}\n"] }]
}], ctorParameters: () => [], propDecorators: { disabled: [{
type: Input
}], isViewOnly: [{
type: Input
}], type: [{
type: Input
}], inputClass: [{
type: Input
}], labelClass: [{
type: Input
}], inputBlockClass: [{
type: Input
}], inputBlockExtraClass: [{
type: Input
}], viewOnlyClass: [{
type: Input
}], wrapperClass: [{
type: Input
}], showLabel: [{
type: Input
}], autoFocus: [{
type: Input
}], enableCharacterCounter: [{
type: Input
}], enableWordCounter: [{
type: Input
}], maxLength: [{
type: Input
}], maxWords: [{
type: Input
}], wordCounterWarningMessage: [{
type: Input
}], changed: [{
type: Output
}], maxLengthReached: [{
type: Output
}], inputBox: [{
type: ViewChild,
args: ['inputBox']
}], model: [{
type: Input
}], field: [{
type: Input
}], append: [{
type: Input
}], prepend: [{
type: Input
}], labelText: [{
type: Input
}] } });
class Search extends SearchAbstract {
}
class BaseSearch extends Search {
}
class SearchResult extends SearchResultAbstract {
}
class BaseSearchResult extends SearchResult {
}
class DdataInputSearchComponent {
constructor(elementRef, router) {
this.elementRef = elementRef;
this.router = router;
this.model = new BaseSearch().init();
this.pageNumber = 0;
this.service = new ProxyFactoryService().get(BaseSearch);
this.icon = {
search: faSearch
};
this.isActive = new BehaviorSubject(false);
this.models = [];
this.paginate = new Paginate(BaseSearchResult);
this.spinner = DdataCoreModule.InjectorInstance.get(SpinnerService);
}
clickout(event) {
if (!this.elementRef.nativeElement.contains(event.target)) {
// click out of component
this.close();
}
}
ngOnDestroy() {
this.isActive.next(false);
}
close() {
this.models = [];
this.isActive.next(false);
}
search() {
// don't run if search string is empty, but reset models & close previous connection
if (this.model.searchText === '') {
this.isActive.next(false);
this.models = [];
return;
}
// close previous connection
this.isActive.next(false);
return fromEvent(this.searchInput.nativeElement, 'keyup').pipe(
// run after 500 ms of last keyup
debounceTime(500),
// run only if value is changed
distinctUntilChanged(),
// run only if search