<!DOCTYPE html>
<html>
<head>
<base href="." />
<title>angular2 playground</title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"></style>
<script src="https://cdn.jsdelivr.net/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- jQuery querybuilder plugin -->
<script src="https://cdn.jsdelivr.net/jquery.query-builder/2.4.1/js/query-builder.standalone.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/jquery.query-builder/2.4.1/css/query-builder.default.min.css"></style>
<script src="es-querybuilder.js"></script>
<script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js/dist/zone.js"></script>
<script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
<script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
/* Styles go here */
### Angular Starter Plunker - Typescript
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
paths: {
'npm:': 'https://unpkg.com/'
},
//map tells the System loader where to look for things
map: {
'app': './src',
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
'rxjs': 'npm:rxjs',
'typescript': 'npm:typescript@2.0.2/lib/typescript.js'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
}
}
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';
platformBrowserDynamic().bootstrapModule(AppModule)
//our root app component
import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {AppComponent} from './app.component'
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
})
export class App {
name:string;
constructor() {
this.name = 'Angular2'
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
import { Component, OnInit } from '@angular/core';
declare var jQuery:any = window.jQuery;
@Component({
selector: 'my-app',
template: `
<h1>Hello {{name}}</h1>
<div id="builder"></div>
<button (click)="reset()">reset</button>
<button (click)="getRules()">Rules</button>
<button (click)="getESBool()">ES</button>
`
})
export class AppComponent implements OnInit {
name = 'Angular';
rules_basic: any = {};
private _queryBuilder(initilal_rules: any) {
$('#builder').queryBuilder({
plugins: ['bt-tooltip-errors'],
filters: [{
id: 'name',
label: 'Name',
type: 'string'
}, {
id: 'category',
label: 'Category',
type: 'integer',
input: 'select',
values: {
1: 'Books',
2: 'Movies',
3: 'Music',
4: 'Tools',
5: 'Goodies',
6: 'Clothes'
},
operators: ['equal', 'not_equal', 'in', 'not_in', 'is_null', 'is_not_null']
}, {
id: 'in_stock',
label: 'In stock',
type: 'integer',
input: 'radio',
values: {
1: 'Yes',
0: 'No'
},
operators: ['equal']
}, {
id: 'price',
label: 'Price',
type: 'double',
validation: {
min: 0,
step: 0.01
}
}, {
id: 'id',
label: 'Identifier',
type: 'string',
placeholder: '____-____-____',
operators: ['equal', 'not_equal'],
validation: {
format: /^.{4}-.{4}-.{4}$/
}
}],
rules: initilal_rules
});
}
ngOnInit() {
let $ = jQuery;
this.rules_basic = {
condition: 'AND',
rules: [{
id: 'price',
operator: 'less',
value: 10.25
}, {
condition: 'OR',
rules: [{
id: 'category',
operator: 'equal',
value: 2
}, {
id: 'category',
operator: 'equal',
value: 1
}]
}]
};
this._queryBuilder(this.rules_basic);
}
reset() {
$('#builder-basic').queryBuilder('reset');
}
setRules(rules: any) {
$('#builder').queryBuilder('setRules', rules);
}
getRules() {
var result = $('#builder').queryBuilder('getRules');
if (!jQuery.isEmptyObject(result)) {
alert(JSON.stringify(result, null, 2));
}
return result;
}
getESBool() {
var result = $('#builder').queryBuilder('getESBool');
console.debug(result)
if (!jQuery.isEmptyObject(result)) {
alert(JSON.stringify(result, null, 2));
}
return result;
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
/*
* jQuery QueryBuilder Elasticsearch 'bool' query support
* https://github.com/mistic100/jQuery-QueryBuilder
* https://www.elastic.co/
* https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
*/
// Register plugin
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery', 'query-builder'], factory);
}
else {
factory(root.jQuery);
}
}(this, function($) {
"use strict";
var QueryBuilder = $.fn.queryBuilder;
// DEFAULT CONFIG
// ===============================
QueryBuilder.defaults({
ESBoolOperators: {
equal: function(v){ return v; },
not_equal: function(v){ return v; },
less: function(v){ return {'lt': v}; },
less_or_equal: function(v){ return {'lte': v}; },
greater: function(v){ return {'gt': v}; },
greater_or_equal: function(v){ return {'gte': v}; },
between: function(v){ return {'gte': v[0], 'lte': v[1]}; },
in : function(v){ return v.split(',').map(function(e) { return e.trim();}); },
not_in: function(v){ return v.split(',').map(function(e) { return e.trim();}); },
is_null: function(v){ return v; },
is_not_null: function(v){ return v; }
},
ESQueryStringQueryOperators: {
is_not_null: function(){ return "_exists_:"; },
is_null: function(){ return "_missing_:";},
contains: function(v){ return v; },
between: function(v){ return '[' + v[0] + ' TO '+ v[1] + "]"; },
}
});
// PUBLIC METHODS
// ===============================
QueryBuilder.extend({
/**
* Get rules as an elasticsearch bool query
* @param data {object} (optional) rules
* @return {object}
*/
getESBool: function(data) {
data = (data===undefined) ? this.getRules() : data;
var that = this;
return (function parse(data) {
if (!data.condition) {
data.condition = that.settings.default_condition;
}
if (['AND', 'OR'].indexOf(data.condition.toUpperCase()) === -1) {
throw new Error(
'Unable to build Elasticsearch bool query with condition "{0}"'
.replace('{0}', data.condition)
);
}
if (!data.rules) {
return {};
}
var parts = {};
parts.add = function (k, v) {
if (this.hasOwnProperty(k)) { this[k].push(v) }
else { this[k] = [v] }
};
data.rules.forEach(function(rule) {
function get_value(rule) {
if (rule.data && rule.data.hasOwnProperty('transform')) {
return window[rule.data.transform].call(this, rule.value);
} else {
return rule.value;
}
}
function make_query(rule) {
var mdb = that.settings.ESBoolOperators[rule.operator],
ope = that.getOperatorByType(rule.operator),
part = {};
if (mdb === undefined) {
throw new Error(
'Unknown elasticsearch operation for operator "{0}"'
.replace('{0}', rule.operator)
);
}
if (ope.nb_inputs !== 0) {
var es_key_val = {};
es_key_val[rule.field] = mdb.call(that, get_value(rule));
part[getQueryDSLWord(rule)] = es_key_val;
}
if (rule.operator === 'is_null' || rule.operator === 'is_not_null') {
part = {exists: {field: rule.field }};
}
// this is a corner case, when we have an "or" group and a negative operator,
// we express this with a sub boolean query and must_not.
if (data.condition === 'OR' && (rule.operator === 'not_equal' || rule.operator === 'not_in' || rule.operator === 'is_null')) {
return {'bool': {'must_not': [part]}}
} else {
return part
}
}
var clause = getClauseWord(data.condition, rule.operator);
if (rule.rules && rule.rules.length>0) {
parts.add(clause, parse(rule));
} else {
parts.add(clause, make_query(rule));
}
});
delete parts.add;
return {'bool': parts}
}(data));
},
/**
* Get rules as an elasticsearch query string query
* @param data {object} (optional) rules
* @return {object}
*/
getESQueryStringQuery: function(data) {
data = (data===undefined) ? this.getRules() : data;
var that = this;
return (function parse(data) {
if (!data.condition) {
data.condition = that.settings.default_condition;
}
if (['AND', 'OR'].indexOf(data.condition.toUpperCase()) === -1) {
throw new Error(
'Unable to build Elasticsearch query String query with condition "{0}"'
.replace('{0}', data.condition)
);
}
if (!data.rules) {
return "";
}
// generate query string
var parts = "";
data.rules.forEach(function(rule, index) {
function get_value(rule) {
return rule.value;
}
function make_query(rule) {
var mdb = that.settings.ESQueryStringQueryOperators[rule.operator],
ope = that.getOperatorByType(rule.operator),
part = "";
if (mdb === undefined) {
throw new Error(
'Unknown elasticsearch operation for operator "{0}"'
.replace('{0}', rule.operator)
);
}
var es_key_val = "";
if (ope.nb_inputs !== 0) {
es_key_val += rule.field + ":" + mdb.call(that, rule.value);
part += es_key_val;
}
else if (ope.nb_inputs === 0) {
es_key_val += mdb.call(that, rule.value) + rule.field;
part += es_key_val;
}
if(data.rules[index+1]) {
return part + " " + data.condition + " ";
}
else {
return part;
}
}
if (rule.rules && rule.rules.length>0) {
parts += "(" + parse(rule) + ")";
} else {
parts += make_query(rule);
}
});
return parts;
}(data));
}
});
/**
* Get the right type of query term in elasticsearch DSL
*/
function getQueryDSLWord(rule) {
var term = /^(equal|not_equal)$/.exec(rule.operator),
wildcard = /.(\*|\?)/.exec(rule.value),
terms = /^(in|not_in)$/.exec(rule.operator);
if (term !== null && wildcard !== null) { return 'wildcard'; }
if (term !== null) { return 'term'; }
if (terms !== null) { return 'terms'; }
return 'range';
}
/**
* Get the right type of clause in the bool query
*/
function getClauseWord(condition, operator) {
if (condition === 'AND' && (operator !== 'not_equal' && operator !== 'not_in' && operator !== 'is_null')) { return 'must' }
if (condition === 'AND' && (operator === 'not_equal' || operator == 'not_in' || operator === 'is_null')) { return 'must_not' }
if (condition === 'OR') { return 'should' }
}
}));