UNPKG

ngx-ntk-query-builder

Version:

Angular query builder

410 lines (403 loc) 46.7 kB
import * as i0 from '@angular/core'; import { Injectable, forwardRef, Input, Component, NgModule } from '@angular/core'; import * as i5 from '@angular/forms'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import * as i1 from '@ngx-translate/core'; import { TranslateService, TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { of, forkJoin } from 'rxjs'; import { catchError } from 'rxjs/operators'; import * as i2 from '@angular/common/http'; import { HttpClient } from '@angular/common/http'; import * as i4 from '@angular/common'; import { CommonModule } from '@angular/common'; import { TranslateHttpLoader } from '@ngx-translate/http-loader'; class TranslateUiService { constructor(translateService, http) { this.translateService = translateService; this.http = http; this.availableLanguages = ['en', 'fa', 'fr', 'ru']; this.translationPath = './assets/i18n/ngx-ntk-query-builder/'; } init(language = null) { if (language) { // Initialize one specific language this.loadTranslation(language).subscribe((translations) => { this.translateService.setTranslation(language, translations, true); this.translateService.use(language); }, (error) => { console.warn(`Failed to load translation for ${language}, falling back to English`); this.loadTranslation('en').subscribe((enTranslations) => { this.translateService.setTranslation(language, enTranslations, true); this.translateService.use(language); }); }); } else { // Initialize all languages const loadPromises = this.availableLanguages.map((lang) => this.loadTranslation(lang).pipe(catchError((error) => { console.warn(`Failed to load translation for ${lang}`); return of(null); }))); forkJoin(loadPromises).subscribe((results) => { results.forEach((translations, index) => { if (translations) { const lang = this.availableLanguages[index]; this.translateService.setTranslation(lang, translations, true); } }); }); } } loadTranslation(language) { return this.http.get(`${this.translationPath}${language}.json`); } setLanguage(language) { this.translateService.use(language); } getCurrentLanguage() { return this.translateService.currentLang; } getAvailableLanguages() { return this.availableLanguages; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TranslateUiService, deps: [{ token: i1.TranslateService }, { token: i2.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TranslateUiService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TranslateUiService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.TranslateService }, { type: i2.HttpClient }] }); class OperatorsService { constructor(translate) { this.translate = translate; this.INPUT_TYPE_STRING = 'string'; this.INPUT_TYPE_INTEGER = 'integer'; this.INPUT_TYPE_DOUBLE = 'double'; this.INPUT_TYPE_TIME = 'time'; this.INPUT_TYPE_DATE = 'date'; this.INPUT_TYPE_SELECT = 'select'; this.INPUT_TYPE_BOOLEAN = 'boolean'; this.INPUT_TYPE_MULTI_SELECT = 'multi_select'; this.NULLABLE_OPERATORS = ['is_null', 'is_not_null']; this.EMPTY_OPERATORS = ['is_empty', 'is_not_empty']; this.MULTI_SELECT_OPERATORS = ['in', 'not_in']; this.defaultOperator = 'equal'; this.operatorsMap = { string: ['equal', 'not_equal', 'contains', 'not_contains', 'begins_with', 'not_begins_with', 'ends_with', 'not_ends_with'], integer: ['equal', 'not_equal', 'greater', 'greater_or_equal', 'less', 'less_or_equal'], double: ['equal', 'not_equal', 'greater', 'greater_or_equal', 'less', 'less_or_equal'], time: ['equal', 'not_equal', 'greater', 'greater_or_equal', 'less', 'less_or_equal'], date: ['equal', 'not_equal', 'greater', 'greater_or_equal', 'less', 'less_or_equal'], select: ['equal', 'not_equal', ...this.MULTI_SELECT_OPERATORS], boolean: ['equal'], }; this.operatorsDisplayNames = { equal: 'querybuilder.equal', not_equal: 'querybuilder.not_equal', contains: 'querybuilder.contains', not_contains: 'querybuilder.not_contains', begins_with: 'querybuilder.begins_with', not_begins_with: 'querybuilder.not_begins_with', ends_with: 'querybuilder.ends_with', not_ends_with: 'querybuilder.not_ends_with', greater: 'querybuilder.greater', greater_or_equal: 'querybuilder.greater_or_equal', less: 'querybuilder.less', less_or_equal: 'querybuilder.less_or_equal', is_null: 'querybuilder.is_null', is_not_null: 'querybuilder.is_not_null', is_empty: 'querybuilder.is_empty', is_not_empty: 'querybuilder.is_not_empty', in: 'querybuilder.in', not_in: 'querybuilder.not_in' }; this.operatorsDisplayNames___old = { equal: 'Equals', not_equal: 'Does not equal', contains: 'Contains', not_contains: 'Does not contain', begins_with: 'Begins with', not_begins_with: 'Does not begins with', ends_with: 'Ends with', not_ends_with: 'Does not end with', greater: 'Greater than', greater_or_equal: 'Greater than or equal', less: 'Less than', less_or_equal: 'Less than or equal', is_null: 'Is null', is_not_null: 'Is not null', is_empty: 'Is empty', is_not_empty: 'Is not empty', in: 'In', not_in: 'Not in' }; } getOperators(rule, fieldMap) { if (!this.getAvailableTypes().includes(rule.type)) { console.error('Type of rule is not valid. Please use one of the following types: ' + this.getAvailableTypes().join(', ')); } let operators = this.operatorsMap[rule.type]; // allow nullable if (fieldMap[rule.field].settings && fieldMap[rule.field].settings.nullableOperators) { operators = [...operators, ...this.NULLABLE_OPERATORS]; } // allow empty if (fieldMap[rule.field].settings && fieldMap[rule.field].settings.emptyOperators) { operators = [...operators, ...this.EMPTY_OPERATORS]; } return operators; } getDefaultOperator() { return this.defaultOperator; } getOperatorsWithoutInput() { return [...this.NULLABLE_OPERATORS, ...this.EMPTY_OPERATORS]; } getOperatorDisplayName(operator) { if (this.operatorsDisplayNames[operator]) { return this.operatorsDisplayNames[operator]; } return operator; } getAvailableTypes() { return [ this.INPUT_TYPE_STRING, this.INPUT_TYPE_INTEGER, this.INPUT_TYPE_DOUBLE, this.INPUT_TYPE_TIME, this.INPUT_TYPE_DATE, this.INPUT_TYPE_SELECT, this.INPUT_TYPE_BOOLEAN ]; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OperatorsService, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OperatorsService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OperatorsService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.TranslateService }] }); class NgxQueryBuilderComponent { set language(value) { this._language = value; this.translateUiService.init(value); this.translate.use(this.language); } get language() { return this._language; } constructor(translate, translateUiService, operatorsService) { this.translate = translate; this.translateUiService = translateUiService; this.operatorsService = operatorsService; this._language = 'en'; this.fieldMap = {}; this.settings = {}; this.disabled = false; this.data = this.getEmptyRuleSetData(); /**** ControlValueAccessor START ****/ this.onChange = (data) => { }; this.onTouched = () => { }; translate.setDefaultLang('en'); translate.use('en'); } ngOnInit() { if (typeof this.fieldMap !== 'object') { throw new Error('fieldMap must be an object'); } if (typeof this.settings !== 'object') { throw new Error('settings must be an object'); } } writeValue(data) { this.data = data || this.getEmptyRuleSetData(); } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; } /**** ControlValueAccessor END ****/ addRule() { if (this.disabled) { return; } this.data.rules.push({ field: this.getFields()[0].value, type: this.getFields()[0].type, operator: this.operatorsService.getDefaultOperator(), }); this.onChange(this.data); this.onTouched(); } removeRule(index) { if (this.disabled) { return; } this.data.rules.splice(index, 1); this.onChange(this.data); this.onTouched(); } addRuleSet() { if (this.disabled) { return; } this.data.rules.push(this.getEmptyRuleSetData()); this.onChange(this.data); this.onTouched(); } removeRuleSet(index) { if (this.disabled) { return; } if (this.hasParentRuleSet()) { this.parent.rules.splice(index, 1); } this.onChange(this.data); this.onTouched(); } changeCondition(value) { if (this.disabled) { return; } this.data.condition = value; this.onChange(this.data); this.onTouched(); } changeField(rule, index) { this.data.rules[index].type = this.fieldMap[rule.field].type; this.data.rules[index].operator = this.operatorsService.getDefaultOperator(); this.data.rules[index].value = undefined; this.onChange(this.data); this.onTouched(); } hasParentRuleSet() { return !!this.parent; } getEmptyRuleSetData() { return { condition: 'and', rules: [] }; } getFields() { return Object.keys(this.fieldMap).map((value) => { const field = this.fieldMap[value]; field.value = value; return field; }); } getInputType(rule) { if (!this.fieldMap[rule.field]) { throw new Error(`No configuration for field '${rule.field}' was found!`); } const type = this.fieldMap[rule.field].type; if (this.operatorsService.getOperatorsWithoutInput().includes(rule.operator)) { return null; // No displayed input } if (this.operatorsService.MULTI_SELECT_OPERATORS.includes(rule.operator)) { return type === this.operatorsService.INPUT_TYPE_SELECT ? this.operatorsService.INPUT_TYPE_MULTI_SELECT : type; } return type; } getRuleOptions(rule) { return this.fieldMap[rule.field].options ? this.fieldMap[rule.field].options : []; } convertToRuleSet(model) { return model; } convertToRule(model) { return model; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxQueryBuilderComponent, deps: [{ token: i1.TranslateService }, { token: TranslateUiService }, { token: OperatorsService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: NgxQueryBuilderComponent, isStandalone: false, selector: "ngx-ntk-query-builder", inputs: { language: "language", fieldMap: "fieldMap", settings: "settings", disabled: "disabled", data: "data", parent: "parent", index: "index" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgxQueryBuilderComponent), multi: true, }, ], ngImport: i0, template: "<div class=\"ngx-ntk-query-builder\" [ngClass]=\"{ disabled: disabled }\">\r\n <div class=\"ngx-ntk-query-group-controls\">\r\n <div class=\"ngx-condition-switcher\">\r\n <div>\r\n <input\r\n name=\"{{ 'condition' + index }}\"\r\n type=\"radio\"\r\n class=\"ngx-switch-radio\"\r\n [(ngModel)]=\"data.condition\"\r\n value=\"and\"\r\n #andOption\r\n />\r\n <label\r\n (click)=\"changeCondition(andOption.value)\"\r\n class=\"ngx-ntk-query-control ngx-switch-label\"\r\n >\r\n {{ \"querybuilder.And\" | translate }}</label\r\n >\r\n </div>\r\n <div>\r\n <input\r\n name=\"{{ 'condition' + index }}\"\r\n type=\"radio\"\r\n class=\"ngx-switch-radio\"\r\n [(ngModel)]=\"data.condition\"\r\n value=\"or\"\r\n #orOption\r\n />\r\n <label\r\n (click)=\"changeCondition(orOption.value)\"\r\n class=\"ngx-ntk-query-control ngx-switch-label\"\r\n >{{ \"querybuilder.Or\" | translate }}</label\r\n >\r\n </div>\r\n </div>\r\n <div class=\"ngx-actions\">\r\n <button\r\n type=\"button\"\r\n class=\"ngx-ntk-query-control ngx-ntk-query-btn ngx-ntk-query-btn-add\"\r\n (click)=\"addRule()\"\r\n >\r\n {{ \"querybuilder.AddRule\" | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"ngx-ntk-query-control ngx-ntk-query-btn ngx-ntk-query-btn-add\"\r\n (click)=\"addRuleSet()\"\r\n >\r\n {{ \"querybuilder.AddGroup\" | translate }}\r\n </button>\r\n <ng-container *ngIf=\"hasParentRuleSet()\">\r\n <button\r\n type=\"button\"\r\n class=\"ngx-ntk-query-control ngx-ntk-query-btn ngx-ntk-query-btn-remove\"\r\n (click)=\"removeRuleSet(index)\"\r\n >\r\n {{ \"querybuilder.Remove\" | translate }}\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"ngx-ntk-query-conditions\">\r\n <ul *ngIf=\"data.rules && data.rules.length > 0\">\r\n <li *ngFor=\"let child of data.rules; let i = index\" class=\"ngx-connector\">\r\n <!-- rule -->\r\n <ng-container *ngIf=\"!child['rules']\">\r\n <div class=\"ngx-rule-wrap\">\r\n <div class=\"ngx-rule\">\r\n <div class=\"ngx-field\">\r\n <select\r\n class=\"ngx-ntk-query-control ngx-ntk-query-select\"\r\n [(ngModel)]=\"child['field']\"\r\n (change)=\"changeField(convertToRule(child), i)\"\r\n [disabled]=\"disabled\"\r\n >\r\n <option\r\n *ngFor=\"let field of getFields()\"\r\n [value]=\"field.value\"\r\n >\r\n {{ field.name }}\r\n </option>\r\n </select>\r\n </div>\r\n <div class=\"ngx-operator\">\r\n <select\r\n class=\"ngx-ntk-query-control ngx-ntk-query-select\"\r\n [(ngModel)]=\"child['operator']\"\r\n [disabled]=\"disabled\"\r\n >\r\n <option\r\n *ngFor=\"\r\n let operator of operatorsService.getOperators(\r\n convertToRule(child),\r\n fieldMap\r\n )\r\n \"\r\n [value]=\"operator\"\r\n >\r\n {{\r\n this.translate.get(\r\n operatorsService.getOperatorDisplayName(operator)\r\n ) | async\r\n }}\r\n </option>\r\n </select>\r\n </div>\r\n <div\r\n class=\"ngx-value\"\r\n [ngSwitch]=\"getInputType(convertToRule(child))\"\r\n >\r\n <!-- STING -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_STRING\"\r\n >\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"text\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- INTEGER -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_INTEGER\"\r\n >\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"number\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- DOUBLE -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_DOUBLE\"\r\n >\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"number\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- DATE -->\r\n <ng-container *ngSwitchCase=\"operatorsService.INPUT_TYPE_DATE\">\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"date\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- TIME -->\r\n <ng-container *ngSwitchCase=\"operatorsService.INPUT_TYPE_TIME\">\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"time\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- BOOLEAN -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_BOOLEAN\"\r\n >\r\n <div class=\"ngx-ntk-query-boolean-wrap\">\r\n <div class=\"ngx-boolean\">\r\n <input\r\n id=\"{{ 'booleanYes' + i }}\"\r\n name=\"{{ 'boolean' + i }}\"\r\n type=\"radio\"\r\n class=\"ngx-radio-btn\"\r\n [(ngModel)]=\"child['value']\"\r\n [value]=\"true\"\r\n [disabled]=\"disabled\"\r\n />\r\n <label for=\"{{ 'booleanYes' + i }}\" class=\"ngx-label\">{{\r\n \"querybuilder.Yes\" | translate\r\n }}</label>\r\n </div>\r\n <div class=\"ngx-boolean\">\r\n <input\r\n id=\"{{ 'booleanNo' + i }}\"\r\n name=\"{{ 'boolean' + i }}\"\r\n type=\"radio\"\r\n class=\"ngx-radio-btn\"\r\n [(ngModel)]=\"child['value']\"\r\n [value]=\"false\"\r\n [disabled]=\"disabled\"\r\n />\r\n <label for=\"{{ 'booleanNo' + i }}\" class=\"ngx-label\">{{\r\n \"querybuilder.No\" | translate\r\n }}</label>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- SELECT -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_SELECT\"\r\n >\r\n <select\r\n class=\"ngx-ntk-query-control ngx-ntk-query-select\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n >\r\n <option\r\n *ngFor=\"let opt of getRuleOptions(convertToRule(child))\"\r\n [value]=\"opt.value\"\r\n >\r\n {{ opt.name }}\r\n </option>\r\n </select>\r\n </ng-container>\r\n\r\n <!-- MULTI_SELECT -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_MULTI_SELECT\"\r\n >\r\n <select\r\n class=\"ngx-ntk-query-control ngx-ntk-query-multi-select\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n multiple\r\n >\r\n <option\r\n *ngFor=\"let opt of getRuleOptions(convertToRule(child))\"\r\n [ngValue]=\"opt.value\"\r\n >\r\n {{ opt.name }}\r\n </option>\r\n </select>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"ngx-rule-controls\">\r\n <button\r\n type=\"button\"\r\n class=\"ngx-ntk-query-control ngx-ntk-query-btn ngx-ntk-query-btn-remove\"\r\n (click)=\"removeRule(i)\"\r\n >\r\n {{ \"querybuilder.Remove\" | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- rule set -->\r\n <ng-container *ngIf=\"child['rules']\">\r\n <ngx-ntk-query-builder\r\n [data]=\"convertToRuleSet(child)\"\r\n [fieldMap]=\"fieldMap\"\r\n [parent]=\"data\"\r\n [disabled]=\"disabled\"\r\n [index]=\"i\"\r\n >\r\n </ngx-ntk-query-builder>\r\n </ng-container>\r\n </li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [".ngx-ntk-query-builder.disabled{opacity:.5}.ngx-ntk-query-builder.disabled .ngx-ntk-query-btn-add:hover{background-color:#5cb85c;border-color:#4cae4c}.ngx-ntk-query-builder.disabled .ngx-ntk-query-btn-remove:hover{background-color:#dc3545;border-color:#dc3545}.ngx-ntk-query-group-controls{display:flex}.ngx-ntk-query-group-controls .ngx-condition-switcher{flex:1 0 auto}.ngx-ntk-query-group-controls .ngx-condition-switcher .ngx-switch-label{float:left;margin-bottom:0;font-weight:400;text-align:center;text-shadow:none;box-sizing:border-box;background-color:#337ab7;border-color:#2e6da4;color:#fff;transition-duration:.3s}.ngx-ntk-query-group-controls .ngx-condition-switcher .ngx-switch-label:hover{cursor:pointer;background-color:#286090}.ngx-ntk-query-group-controls .ngx-condition-switcher .ngx-switch-radio{position:absolute;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.ngx-ntk-query-group-controls .ngx-condition-switcher .ngx-switch-radio:checked+.ngx-switch-label{color:#fff;background-color:#286090;border-color:#204d74}.ngx-ntk-query-group-controls .ngx-actions{display:flex;margin-right:10px}.ngx-ntk-query-conditions ul{margin:0;padding:0 10px 0 25px}.ngx-ntk-query-conditions li{list-style:none}.ngx-ntk-query-conditions li.ngx-connector{position:relative;border:1px solid #cccccc;margin:8px 0;padding:10px}.ngx-ntk-query-conditions li.ngx-connector:before{top:-9px;border-width:0 0 2px 2px}.ngx-ntk-query-conditions li.ngx-connector:after{border-width:0 0 0 2px;top:50%}.ngx-ntk-query-conditions li.ngx-connector:before,.ngx-ntk-query-conditions li.ngx-connector:after{content:\"\";left:-14px;border-color:#ccc;border-style:solid;width:12px;height:calc(50% + 9px);position:absolute}.ngx-ntk-query-conditions li.ngx-connector:last-child:after{content:none}.ngx-ntk-query-conditions .ngx-rule-wrap{display:flex;flex-wrap:wrap}.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule{flex:1;margin-right:10px;display:flex;flex-wrap:wrap}.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule .ngx-field,.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule .ngx-operator,.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule .ngx-value{display:flex;align-items:center;padding:5px 0;margin-right:15px}.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule-controls{padding:8px 0}.ngx-ntk-query-control{padding:0 .75rem;height:40px;line-height:40px;font-size:1rem}.ngx-ntk-query-input,.ngx-ntk-query-select,.ngx-ntk-query-multi-select{display:block;width:100%;color:#495057;padding:.5rem .75rem;background-color:#fff;box-sizing:border-box;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem}.ngx-ntk-query-multi-select{height:auto;max-height:200px}.ngx-ntk-query-boolean-wrap{display:flex;color:#495057}.ngx-ntk-query-btn{display:inline-block;font-weight:400;color:#fff;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;outline:none;transition-duration:.3s}.ngx-ntk-query-btn-add{background-color:#5cb85c;border-color:#4cae4c}.ngx-ntk-query-btn-add:hover{background-color:#449d44;border-color:#398439}.ngx-ntk-query-btn-remove{background-color:#dc3545;border-color:#dc3545}.ngx-ntk-query-btn-remove:hover{background-color:#c82333;border-color:#bd2130}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i5.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.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: i5.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i5.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i5.SelectMultipleControlValueAccessor, selector: "select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i5.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NgxQueryBuilderComponent, selector: "ngx-ntk-query-builder", inputs: ["language", "fieldMap", "settings", "disabled", "data", "parent", "index"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxQueryBuilderComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-ntk-query-builder', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgxQueryBuilderComponent), multi: true, }, ], standalone: false, template: "<div class=\"ngx-ntk-query-builder\" [ngClass]=\"{ disabled: disabled }\">\r\n <div class=\"ngx-ntk-query-group-controls\">\r\n <div class=\"ngx-condition-switcher\">\r\n <div>\r\n <input\r\n name=\"{{ 'condition' + index }}\"\r\n type=\"radio\"\r\n class=\"ngx-switch-radio\"\r\n [(ngModel)]=\"data.condition\"\r\n value=\"and\"\r\n #andOption\r\n />\r\n <label\r\n (click)=\"changeCondition(andOption.value)\"\r\n class=\"ngx-ntk-query-control ngx-switch-label\"\r\n >\r\n {{ \"querybuilder.And\" | translate }}</label\r\n >\r\n </div>\r\n <div>\r\n <input\r\n name=\"{{ 'condition' + index }}\"\r\n type=\"radio\"\r\n class=\"ngx-switch-radio\"\r\n [(ngModel)]=\"data.condition\"\r\n value=\"or\"\r\n #orOption\r\n />\r\n <label\r\n (click)=\"changeCondition(orOption.value)\"\r\n class=\"ngx-ntk-query-control ngx-switch-label\"\r\n >{{ \"querybuilder.Or\" | translate }}</label\r\n >\r\n </div>\r\n </div>\r\n <div class=\"ngx-actions\">\r\n <button\r\n type=\"button\"\r\n class=\"ngx-ntk-query-control ngx-ntk-query-btn ngx-ntk-query-btn-add\"\r\n (click)=\"addRule()\"\r\n >\r\n {{ \"querybuilder.AddRule\" | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"ngx-ntk-query-control ngx-ntk-query-btn ngx-ntk-query-btn-add\"\r\n (click)=\"addRuleSet()\"\r\n >\r\n {{ \"querybuilder.AddGroup\" | translate }}\r\n </button>\r\n <ng-container *ngIf=\"hasParentRuleSet()\">\r\n <button\r\n type=\"button\"\r\n class=\"ngx-ntk-query-control ngx-ntk-query-btn ngx-ntk-query-btn-remove\"\r\n (click)=\"removeRuleSet(index)\"\r\n >\r\n {{ \"querybuilder.Remove\" | translate }}\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"ngx-ntk-query-conditions\">\r\n <ul *ngIf=\"data.rules && data.rules.length > 0\">\r\n <li *ngFor=\"let child of data.rules; let i = index\" class=\"ngx-connector\">\r\n <!-- rule -->\r\n <ng-container *ngIf=\"!child['rules']\">\r\n <div class=\"ngx-rule-wrap\">\r\n <div class=\"ngx-rule\">\r\n <div class=\"ngx-field\">\r\n <select\r\n class=\"ngx-ntk-query-control ngx-ntk-query-select\"\r\n [(ngModel)]=\"child['field']\"\r\n (change)=\"changeField(convertToRule(child), i)\"\r\n [disabled]=\"disabled\"\r\n >\r\n <option\r\n *ngFor=\"let field of getFields()\"\r\n [value]=\"field.value\"\r\n >\r\n {{ field.name }}\r\n </option>\r\n </select>\r\n </div>\r\n <div class=\"ngx-operator\">\r\n <select\r\n class=\"ngx-ntk-query-control ngx-ntk-query-select\"\r\n [(ngModel)]=\"child['operator']\"\r\n [disabled]=\"disabled\"\r\n >\r\n <option\r\n *ngFor=\"\r\n let operator of operatorsService.getOperators(\r\n convertToRule(child),\r\n fieldMap\r\n )\r\n \"\r\n [value]=\"operator\"\r\n >\r\n {{\r\n this.translate.get(\r\n operatorsService.getOperatorDisplayName(operator)\r\n ) | async\r\n }}\r\n </option>\r\n </select>\r\n </div>\r\n <div\r\n class=\"ngx-value\"\r\n [ngSwitch]=\"getInputType(convertToRule(child))\"\r\n >\r\n <!-- STING -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_STRING\"\r\n >\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"text\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- INTEGER -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_INTEGER\"\r\n >\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"number\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- DOUBLE -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_DOUBLE\"\r\n >\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"number\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- DATE -->\r\n <ng-container *ngSwitchCase=\"operatorsService.INPUT_TYPE_DATE\">\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"date\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- TIME -->\r\n <ng-container *ngSwitchCase=\"operatorsService.INPUT_TYPE_TIME\">\r\n <input\r\n class=\"ngx-ntk-query-control ngx-ntk-query-input\"\r\n type=\"time\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n />\r\n </ng-container>\r\n\r\n <!-- BOOLEAN -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_BOOLEAN\"\r\n >\r\n <div class=\"ngx-ntk-query-boolean-wrap\">\r\n <div class=\"ngx-boolean\">\r\n <input\r\n id=\"{{ 'booleanYes' + i }}\"\r\n name=\"{{ 'boolean' + i }}\"\r\n type=\"radio\"\r\n class=\"ngx-radio-btn\"\r\n [(ngModel)]=\"child['value']\"\r\n [value]=\"true\"\r\n [disabled]=\"disabled\"\r\n />\r\n <label for=\"{{ 'booleanYes' + i }}\" class=\"ngx-label\">{{\r\n \"querybuilder.Yes\" | translate\r\n }}</label>\r\n </div>\r\n <div class=\"ngx-boolean\">\r\n <input\r\n id=\"{{ 'booleanNo' + i }}\"\r\n name=\"{{ 'boolean' + i }}\"\r\n type=\"radio\"\r\n class=\"ngx-radio-btn\"\r\n [(ngModel)]=\"child['value']\"\r\n [value]=\"false\"\r\n [disabled]=\"disabled\"\r\n />\r\n <label for=\"{{ 'booleanNo' + i }}\" class=\"ngx-label\">{{\r\n \"querybuilder.No\" | translate\r\n }}</label>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- SELECT -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_SELECT\"\r\n >\r\n <select\r\n class=\"ngx-ntk-query-control ngx-ntk-query-select\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n >\r\n <option\r\n *ngFor=\"let opt of getRuleOptions(convertToRule(child))\"\r\n [value]=\"opt.value\"\r\n >\r\n {{ opt.name }}\r\n </option>\r\n </select>\r\n </ng-container>\r\n\r\n <!-- MULTI_SELECT -->\r\n <ng-container\r\n *ngSwitchCase=\"operatorsService.INPUT_TYPE_MULTI_SELECT\"\r\n >\r\n <select\r\n class=\"ngx-ntk-query-control ngx-ntk-query-multi-select\"\r\n [(ngModel)]=\"child['value']\"\r\n [disabled]=\"disabled\"\r\n multiple\r\n >\r\n <option\r\n *ngFor=\"let opt of getRuleOptions(convertToRule(child))\"\r\n [ngValue]=\"opt.value\"\r\n >\r\n {{ opt.name }}\r\n </option>\r\n </select>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <div class=\"ngx-rule-controls\">\r\n <button\r\n type=\"button\"\r\n class=\"ngx-ntk-query-control ngx-ntk-query-btn ngx-ntk-query-btn-remove\"\r\n (click)=\"removeRule(i)\"\r\n >\r\n {{ \"querybuilder.Remove\" | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- rule set -->\r\n <ng-container *ngIf=\"child['rules']\">\r\n <ngx-ntk-query-builder\r\n [data]=\"convertToRuleSet(child)\"\r\n [fieldMap]=\"fieldMap\"\r\n [parent]=\"data\"\r\n [disabled]=\"disabled\"\r\n [index]=\"i\"\r\n >\r\n </ngx-ntk-query-builder>\r\n </ng-container>\r\n </li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [".ngx-ntk-query-builder.disabled{opacity:.5}.ngx-ntk-query-builder.disabled .ngx-ntk-query-btn-add:hover{background-color:#5cb85c;border-color:#4cae4c}.ngx-ntk-query-builder.disabled .ngx-ntk-query-btn-remove:hover{background-color:#dc3545;border-color:#dc3545}.ngx-ntk-query-group-controls{display:flex}.ngx-ntk-query-group-controls .ngx-condition-switcher{flex:1 0 auto}.ngx-ntk-query-group-controls .ngx-condition-switcher .ngx-switch-label{float:left;margin-bottom:0;font-weight:400;text-align:center;text-shadow:none;box-sizing:border-box;background-color:#337ab7;border-color:#2e6da4;color:#fff;transition-duration:.3s}.ngx-ntk-query-group-controls .ngx-condition-switcher .ngx-switch-label:hover{cursor:pointer;background-color:#286090}.ngx-ntk-query-group-controls .ngx-condition-switcher .ngx-switch-radio{position:absolute;clip:rect(0,0,0,0);height:1px;width:1px;border:0;overflow:hidden}.ngx-ntk-query-group-controls .ngx-condition-switcher .ngx-switch-radio:checked+.ngx-switch-label{color:#fff;background-color:#286090;border-color:#204d74}.ngx-ntk-query-group-controls .ngx-actions{display:flex;margin-right:10px}.ngx-ntk-query-conditions ul{margin:0;padding:0 10px 0 25px}.ngx-ntk-query-conditions li{list-style:none}.ngx-ntk-query-conditions li.ngx-connector{position:relative;border:1px solid #cccccc;margin:8px 0;padding:10px}.ngx-ntk-query-conditions li.ngx-connector:before{top:-9px;border-width:0 0 2px 2px}.ngx-ntk-query-conditions li.ngx-connector:after{border-width:0 0 0 2px;top:50%}.ngx-ntk-query-conditions li.ngx-connector:before,.ngx-ntk-query-conditions li.ngx-connector:after{content:\"\";left:-14px;border-color:#ccc;border-style:solid;width:12px;height:calc(50% + 9px);position:absolute}.ngx-ntk-query-conditions li.ngx-connector:last-child:after{content:none}.ngx-ntk-query-conditions .ngx-rule-wrap{display:flex;flex-wrap:wrap}.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule{flex:1;margin-right:10px;display:flex;flex-wrap:wrap}.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule .ngx-field,.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule .ngx-operator,.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule .ngx-value{display:flex;align-items:center;padding:5px 0;margin-right:15px}.ngx-ntk-query-conditions .ngx-rule-wrap .ngx-rule-controls{padding:8px 0}.ngx-ntk-query-control{padding:0 .75rem;height:40px;line-height:40px;font-size:1rem}.ngx-ntk-query-input,.ngx-ntk-query-select,.ngx-ntk-query-multi-select{display:block;width:100%;color:#495057;padding:.5rem .75rem;background-color:#fff;box-sizing:border-box;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem}.ngx-ntk-query-multi-select{height:auto;max-height:200px}.ngx-ntk-query-boolean-wrap{display:flex;color:#495057}.ngx-ntk-query-btn{display:inline-block;font-weight:400;color:#fff;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;outline:none;transition-duration:.3s}.ngx-ntk-query-btn-add{background-color:#5cb85c;border-color:#4cae4c}.ngx-ntk-query-btn-add:hover{background-color:#449d44;border-color:#398439}.ngx-ntk-query-btn-remove{background-color:#dc3545;border-color:#dc3545}.ngx-ntk-query-btn-remove:hover{background-color:#c82333;border-color:#bd2130}\n"] }] }], ctorParameters: () => [{ type: i1.TranslateService }, { type: TranslateUiService }, { type: OperatorsService }], propDecorators: { language: [{ type: Input }], fieldMap: [{ type: Input }], settings: [{ type: Input }], disabled: [{ type: Input }], data: [{ type: Input }], parent: [{ type: Input }], index: [{ type: Input }] } }); class NgxNtkQueryBuilderModule { static forRoot() { return { ngModule: NgxNtkQueryBuilderModule, providers: [TranslateService] }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxNtkQueryBuilderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: NgxNtkQueryBuilderModule, declarations: [NgxQueryBuilderComponent], imports: [CommonModule, FormsModule, i1.TranslateModule], exports: [NgxQueryBuilderComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxNtkQueryBuilderModule, providers: [ TranslateService, ], imports: [CommonModule, FormsModule, TranslateModule.forChild({ loader: { provide: TranslateLoader, useFactory: (http) => new TranslateHttpLoader(http, '/assets/i18n/querybuilder/', '.json'), deps: [HttpClient] } })] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxNtkQueryBuilderModule, decorators: [{ type: NgModule, args: [{ declarations: [ NgxQueryBuilderComponent, ], imports: [ CommonModule, FormsModule, TranslateModule.forChild({ loader: { provide: TranslateLoader, useFactory: (http) => new TranslateHttpLoader(http, '/assets/i18n/querybuilder/', '.json'), deps: [HttpClient] } }), ], exports: [ NgxQueryBuilderComponent, ], providers: [ TranslateService, ] }] }] }); /** * Generated bundle index. Do not edit. */ export { NgxNtkQueryBuilderModule, NgxQueryBuilderComponent }; //# sourceMappingURL=ngx-ntk-query-builder.mjs.map