ngx-ntk-query-builder
Version:
Angular query builder
410 lines (403 loc) • 46.7 kB
JavaScript
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