Coder Social home page Coder Social logo

ukrbublik / react-awesome-query-builder Goto Github PK

View Code? Open in Web Editor NEW
1.8K 31.0 478.0 102.67 MB

User-friendly query builder for React

Home Page: https://ukrbublik.github.io/react-awesome-query-builder

License: MIT License

JavaScript 84.61% Shell 0.22% HTML 0.07% TypeScript 13.18% SCSS 1.92%
reactjs react-component react-components query-builder react antd antdesign sql mongo typescript material-ui ant-design hacktoberfest hacktoberfest2021 query filter

react-awesome-query-builder's Introduction

npm Smoke codecov antd mui bootstrap fluent demo sandbox TS sandbox JS

User-friendly React component to build queries (filters).

Inspired by jQuery QueryBuilder. Using awesome UI frameworks for widgets: Ant Design, Material-UI, Bootstrap. Now Fluent UI is also supported!

See live demo

Edit in codesandbox

Features

Screenshot

  • Highly configurable
  • Fields can be of type:
    • simple (string, number, bool, date/time/datetime, list)
    • structs (will be displayed in selectbox as tree)
    • custom type (dev should add its own widget component in config for this)
  • Comparison operators can be:
    • binary (== != < > ..)
    • unary (is empty, is null)
    • 'between' (for numbers, dates, times)
    • complex operators like 'proximity'
  • RHS can be:
    • values
    • another fields (of same type)
    • functions (arguments also can be values/fields/funcs)
  • LHS can be field or function
  • Reordering (drag-n-drop) support for rules and groups of rules
  • Themes:
  • Export to MongoDb, SQL, JsonLogic, SpEL, ElasticSearch or your custom format
  • Import from JsonLogic, SpEL
  • TypeScript support (see types and demo in TS)
  • Query value and config can be saved/loaded from server

Getting started

From v6 library is divided into packages:

graph LR;
  core((core))-->ui(ui);
  ui-->antd;
  ui-->mui;
  ui-->material;
  ui-->bootstrap;
  ui-->fluent;

ui re-exports from core, other packages re-export from ui. For using this library on frontend you need to install and use only ui (for basic widgets) or one of framework-specific packages (antd / mui / bootstrap / fluent).

For using this library on server-side (Node.js) you need only core. This is useful if you want to pass query value from frontend to backend in JSON format and perform export eg. to SQL on server-side for security reasons.

Example of installation if you use MUI:

npm i @react-awesome-query-builder/mui --save

Note: We use pnpm. If you want to clone this project and run scripts, please install pnpm:

npm install -g pnpm

See basic usage for minimum code example.

See API and config for documentation.

Demo apps

  • pnpm start - demo app with hot reload of demo code and local library code, uses TS, uses complex config to demonstrate anvanced usage, uses all supported UI frameworks.
  • pnpm sandbox-ts - simple demo app, built with Vite, uses TS, uses MUI widgets.
  • pnpm sandbox-js - simplest demo app, built with Vite, not uses TS, uses vanilla widgets.
  • pnpm sandbox-next - advanced demo app with server side, built with Next.js, uses TS, uses MUI widgets, has API to save/load query value and query config from storage.

Usage

Minimal JavaScript example with class component

import React, {Component} from 'react';

// >>>
import { Utils as QbUtils, Query, Builder, BasicConfig } from '@react-awesome-query-builder/ui';
import '@react-awesome-query-builder/ui/css/styles.css';
// or import '@react-awesome-query-builder/ui/css/compact_styles.css';
const InitialConfig = BasicConfig;
// <<<

// You need to provide your own config. See below 'Config format'
const config = {
  ...InitialConfig,
  fields: {
    qty: {
      label: 'Qty',
      type: 'number',
      fieldSettings: {
        min: 0,
      },
      valueSources: ['value'],
      preferWidgets: ['number'],
    },
    price: {
      label: 'Price',
      type: 'number',
      valueSources: ['value'],
      fieldSettings: {
        min: 10,
        max: 100,
      },
      preferWidgets: ['slider', 'rangeslider'],
    },
    name: {
      label: 'Name',
      type: 'text',
    },
    color: {
      label: 'Color',
      type: 'select',
      valueSources: ['value'],
      fieldSettings: {
        listValues: [
          { value: 'yellow', title: 'Yellow' },
          { value: 'green', title: 'Green' },
          { value: 'orange', title: 'Orange' }
        ],
      }
    },
    is_promotion: {
      label: 'Promo?',
      type: 'boolean',
      operators: ['equal'],
      valueSources: ['value'],
    },
  }
};

// You can load query value from your backend storage (for saving see `Query.onChange()`)
const queryValue = {"id": QbUtils.uuid(), "type": "group"};


class DemoQueryBuilder extends Component {
  state = {
    tree: QbUtils.checkTree(QbUtils.loadTree(queryValue), config),
    config: config
  };
  
  render = () => (
    <div>
      <Query
        {...config} 
        value={this.state.tree}
        onChange={this.onChange}
        renderBuilder={this.renderBuilder}
      />
      {this.renderResult(this.state)}
    </div>
  )

  renderBuilder = (props) => (
    <div className="query-builder-container" style={{padding: '10px'}}>
      <div className="query-builder qb-lite">
        <Builder {...props} />
      </div>
    </div>
  )

  renderResult = ({tree: immutableTree, config}) => (
    <div className="query-builder-result">
      <div>Query string: <pre>{JSON.stringify(QbUtils.queryString(immutableTree, config))}</pre></div>
      <div>MongoDb query: <pre>{JSON.stringify(QbUtils.mongodbFormat(immutableTree, config))}</pre></div>
      <div>SQL where: <pre>{JSON.stringify(QbUtils.sqlFormat(immutableTree, config))}</pre></div>
      <div>JsonLogic: <pre>{JSON.stringify(QbUtils.jsonLogicFormat(immutableTree, config))}</pre></div>
    </div>
  )
  
  onChange = (immutableTree, config) => {
    // Tip: for better performance you can apply `throttle` - see `examples/demo`
    this.setState({tree: immutableTree, config: config});

    const jsonTree = QbUtils.getTree(immutableTree);
    console.log(jsonTree);
    // `jsonTree` can be saved to backend, and later loaded to `queryValue`
  }
}
export default DemoQueryBuilder;

Minimal TypeScript example with function component

import React, { useState, useCallback } from "react";

// >>> 
import type { JsonGroup, Config, ImmutableTree, BuilderProps } from '@react-awesome-query-builder/ui';
import { Utils as QbUtils, Query, Builder, BasicConfig } from '@react-awesome-query-builder/ui';
import '@react-awesome-query-builder/ui/css/styles.css';
// or import '@react-awesome-query-builder/ui/css/compact_styles.css';
const InitialConfig = BasicConfig;
// <<<

// You need to provide your own config. See below 'Config format'
const config: Config = {
  ...InitialConfig,
  fields: {
    qty: {
      label: "Qty",
      type: "number",
      fieldSettings: {
        min: 0
      },
      valueSources: ["value"],
      preferWidgets: ["number"]
    },
    price: {
      label: "Price",
      type: "number",
      valueSources: ["value"],
      fieldSettings: {
        min: 10,
        max: 100
      },
      preferWidgets: ["slider", "rangeslider"]
    },
    name: {
      label: 'Name',
      type: 'text',
    },
    color: {
      label: "Color",
      type: "select",
      valueSources: ["value"],
      fieldSettings: {
        listValues: [
          { value: "yellow", title: "Yellow" },
          { value: "green", title: "Green" },
          { value: "orange", title: "Orange" }
        ]
      }
    },
    is_promotion: {
      label: "Promo?",
      type: "boolean",
      operators: ["equal"],
      valueSources: ["value"]
    }
  }
};

// You can load query value from your backend storage (for saving see `Query.onChange()`)
const queryValue: JsonGroup = { id: QbUtils.uuid(), type: "group" };

const DemoQueryBuilder: React.FC = () => {
  const [state, setState] = useState({
    tree: QbUtils.checkTree(QbUtils.loadTree(queryValue), config),
    config: config
  });

  const onChange = useCallback((immutableTree: ImmutableTree, config: Config) => {
    // Tip: for better performance you can apply `throttle` - see `examples/demo`
    setState(prevState => ({ ...prevState, tree: immutableTree, config: config }));

    const jsonTree = QbUtils.getTree(immutableTree);
    console.log(jsonTree);
    // `jsonTree` can be saved to backend, and later loaded to `queryValue`
  }, []);

  const renderBuilder = useCallback((props: BuilderProps) => (
    <div className="query-builder-container" style={{ padding: "10px" }}>
      <div className="query-builder qb-lite">
        <Builder {...props} />
      </div>
    </div>
  ), []);

  return (
    <div>
      <Query
        {...config}
        value={state.tree}
        onChange={onChange}
        renderBuilder={renderBuilder}
      />
      <div className="query-builder-result">
        <div>
          Query string:{" "}
          <pre>
            {JSON.stringify(QbUtils.queryString(state.tree, state.config))}
          </pre>
        </div>
        <div>
          MongoDb query:{" "}
          <pre>
            {JSON.stringify(QbUtils.mongodbFormat(state.tree, state.config))}
          </pre>
        </div>
        <div>
          SQL where:{" "}
          <pre>
            {JSON.stringify(QbUtils.sqlFormat(state.tree, state.config))}
          </pre>
        </div>
        <div>
          JsonLogic:{" "}
          <pre>
            {JSON.stringify(QbUtils.jsonLogicFormat(state.tree, state.config))}
          </pre>
        </div>
      </div>
    </div>
  );
};
export default DemoQueryBuilder;

API

<Query />

Props:

  • {...config} - destructured CONFIG
  • value - query value in internal Immutable format
  • onChange - callback when query value changed. Params: value (in Immutable format), config, actionMeta (details about action which led to the change, see ActionMeta in index.d.ts).
  • renderBuilder - function to render query builder itself. Takes 1 param props you need to pass into <Builder {...props} />.

Notes:

  • Please apply useCallback for onChange and renderBuilder for performance reason
  • If you put query builder component inside Material-UI's <Dialog /> or <Popover />, please:
    • use prop disableEnforceFocus={true} for dialog or popver
    • set css .MuiPopover-root, .MuiDialog-root { z-index: 900 !important; } (or 1000 for AntDesign v3)
  • If you put query builder component inside Fluent-UI's <Panel />, please:
    • set css .ms-Layer.ms-Layer--fixed.root-119 { z-index: 900 !important; }
  • props arg in renderBuilder have actions and dispatch you can use to run actions programmatically (for list of actions see Actions in index.d.ts).

<Builder />

Render this component only inside Query.renderBuilder() like in example above:

  renderBuilder = (props) => (
    <div className="query-builder-container">
      <div className="query-builder qb-lite">
          <Builder {...props} />
      </div>
    </div>
  )

Wrapping <Builder /> in div.query-builder is necessary.
Optionally you can add class .qb-lite to it for showing action buttons (like delete rule/group, add, etc.) only on hover, which will look cleaner.
Wrapping in div.query-builder-container is necessary if you put query builder inside scrollable block.

Utils

  • Save, load:

    getTree (immutableValue, light = true, children1AsArray = true) -> Object

    Convert query value from internal Immutable format to JS object. You can use it to save value on backend in onChange callback of <Query>.
    Tip: Use light = false in case if you want to store query value in your state in JS format and pass it as value of <Query> after applying loadTree() (which is not recommended because of double conversion). See issue #190

    loadTree (jsValue) -> Immutable

    Convert query value from JS format to internal Immutable format. You can use it to load saved value from backend and pass as value prop to <Query> (don't forget to also apply checkTree()).

    checkTree (immutableValue, config) -> Immutable

    Validate query value corresponding to config. Invalid parts of query (eg. if field was removed from config) will be always deleted. Invalid values (values not passing validateValue in config, bad ranges) will be deleted if showErrorMessage is false OR marked with errors if showErrorMessage is true.

    isValidTree (immutableValue) -> Boolean

    If showErrorMessage in config.settings is true, use this method to check is query has bad values.
  • Export:

    queryString (immutableValue, config, isForDisplay = false) -> String

    Convert query value to custom string representation. isForDisplay = true can be used to make string more "human readable".

    mongodbFormat (immutableValue, config) -> Object

    Convert query value to MongoDb query object.

    sqlFormat (immutableValue, config) -> String

    Convert query value to SQL where string.

    spelFormat (immutableValue, config) -> String

    Convert query value to Spring Expression Language (SpEL).

    elasticSearchFormat (immutableValue, config) -> Object

    Convert query value to ElasticSearch query object.

    jsonLogicFormat (immutableValue, config) -> {logic, data, errors}

    Convert query value to JsonLogic format. If there are no errors, logic will be rule object and data will contain all used fields with null values ("template" data).
  • Import:

    loadFromJsonLogic (jsonLogicObject, config) -> Immutable

    Convert query value from JsonLogic format to internal Immutable format.

    _loadFromJsonLogic (jsonLogicObject, config) -> [Immutable, errors]

    loadFromSpel (string, config) -> [Immutable, errors]

    Convert query value from Spring Expression Language (SpEL) format to internal Immutable format.
  • Save/load config from server:

    compressConfig(config, baseConfig) -> ZipConfig

    Returns compressed config that can be serialized to JSON and saved on server.
    ZipConfig is a special format that contains only changes agains baseConfig.
    baseConfig is a config you used as a base for constructing config, like InitialConfig in examples above.
    It depends on UI framework you choose - eg. if you use @react-awesome-query-builder/mui, please provide MuiConfig to baseConfig.

    decompressConfig(zipConfig, baseConfig, ctx?) -> Config

    Converts zipConfig (compressed config you receive from server) to a full config that can be passed to <Query />.
    baseConfig is a config to be used as a base for constructing your config, like InitialConfig in examples above.
    ctx is optional and can contain your custom functions and custom React components used in your config.
    If ctx is provided in 3rd argument, it will inject it to result config, otherwise will copy from basic config in 2nd argument.
    See SSR for more info.
    Note that you should set config.settings.useConfigCompress = true in order for this function to work.

Config format

This library uses config-driven aproach. Config defines what value types, operators are supported, how they are rendered, imported, exported. At minimum, you need to provide your own set of fields as in basic usage.
See CONFIG for full documentation.

SSR

You can save and load config from server with help of utils:

You need these utils because you can't just send config as-is to server, as it contains functions that can't be serialized to JSON.
Note that you need to set config.settings.useConfigCompress = true to enable this feature.

To put it simple:

  • ZipConfig type is a JSON that contains only changes against basic config (differences). At minimum it contains your fields. It does not contain ctx.
  • Utils.decompressConfig() will merge ZipConfig to basic config (and add ctx if passed).

See sandbox_next demo app that demonstrates server-side features.

ctx

Config context is an obligatory part of config starting from version 6.3.0
It is a collection of functions and React components to be used in other parts of config by reference to ctx rather than by reference to imported modules.
The purpose of ctx is to isolate non-serializable part of config.
See config.ctx.

Versions

Version 5 is backward-compatible with 2-4. From version 6 library is divided into packages. It's recommended to update your version to 6.x. You just need to change your imports, see Migration to 6.0.0

Supported versions

Version Supported
6.x
5.x ✔️
4.x ⚠️
3.x
2.x
1.x
0.x

Changelog

See CHANGELOG

Migration to 6.4.0

If you want to enable functions in LHS, please add to config.settings:

fieldSources: ["field", "func"],

Migration to 6.3.0

Now config has new ctx property. Make sure you add it to your config.

Typically you just need to copy it from basic config. So if you create config like this, you don't need to make any changes:

import { MuiConfig } from "@react-awesome-query-builder/mui";
const config = {
  ...MuiConfig,
  fields: {
    // your fields
  },
};

But if you create config without destructuring of basic config, please add ctx:

import { MuiConfig } from "@react-awesome-query-builder/mui";

const config = {
  ctx: MuiConfig.ctx, // needs to be added for 6.3.0+
  conjunctions,
  operators,
  widgets,
  types,
  settings,
  fields,
  funcs
};
export default config;

Migration to 6.2.0

If you use treeselect or treemultiselect type (for AntDesign), please rename listValues to treeValues

Migration to 6.0.0

From version 6 library is divided into packages. Please remove package react-awesome-query-builder and install one of:

Library code is backward-compatible with version 2-5. You just need to change your imports.

- import { Utils, Export, Import, BasicFuncs } from 'react-awesome-query-builder';
+ import { Utils, Export, Import, BasicFuncs } from '@react-awesome-query-builder/ui';

- import { Query, Builder, BasicConfig, Widgets, Operators } from 'react-awesome-query-builder';
+ import { Query, Builder, BasicConfig, VanillaWidgets, CustomOperators } from '@react-awesome-query-builder/ui';

- import AntdConfig from 'react-awesome-query-builder/lib/config/antd';
+ import {AntdConfig} from '@react-awesome-query-builder/antd';
- import MuiConfig from 'react-awesome-query-builder/lib/config/mui';
+ import {MuiConfig} from '@react-awesome-query-builder/mui';
- import MaterialConfig from 'react-awesome-query-builder/lib/config/material';
+ import {MaterialConfig} from '@react-awesome-query-builder/material';
- import BootstrapConfig from 'react-awesome-query-builder/lib/config/bootstrap';
+ import {BootstrapConfig} from '@react-awesome-query-builder/bootstrap';

- import 'react-awesome-query-builder/lib/css/styles.css';
+ import '@react-awesome-query-builder/ui/css/styles.css';
- import 'react-awesome-query-builder/lib/css/compact_styles.css';
+ import '@react-awesome-query-builder/ui/css/compact_styles.css'; // instead of styles.css for more compact look

Note that you should import all types and values from a single package. For example, @react-awesome-query-builder/antd if you use AntDesign - it inherits core and ui:

import {Utils, Query, Builder, AntdConfig} from '@react-awesome-query-builder/antd';

You don't need to install and import ui and core packages in this case, just use antd.
Same for styles - please import from antd package:

import '@react-awesome-query-builder/antd/css/styles.css';

instead of

import '@react-awesome-query-builder/ui/css/styles.css';

If you use vanilla widgets, please install, import and use only @react-awesome-query-builder/ui (it inherits core).

One more thing, if you use Bootstrap widgets, now you need to explicitly import CSS:

import "bootstrap/dist/css/bootstrap.min.css";

Migration to 5.2.0

Breaking change: children1 is now an indexed array (instead of object) in result of Utils.getTree() to preserve items order.
Before:

children1: {
  '<id1>': { type: 'rule', properties: ... },
  '<id2>': { type: 'rule', properties: ... }
}

After:

children1: [
  { id: '<id1>', type: 'rule', properties: ... },
  { id: '<id2>', type: 'rule', properties: ... },
]

Utils.loadTree() is backward comatible with children1 being array or object.
But if you rely on previous format (maybe do post-processing of getTree() result), please use Utils.getTree(tree, true, false) - it will behave same as before this change.

Another breaking change: removeIncompleteRulesOnLoad and removeEmptyGroupsOnLoad now default to true, set them to false in your settings to preserve the behaviour before 5.2.0.

Migration to 4.9.0

Version 4.9.0 has a breaking change for operators is_empty and is_not_empty.
Now these operators can be used for text type only (for other types they will be auto converted to is_null/is_not_null during loading of query value created with previous versions).
Changed meaning of is_empty - now it's just strict comparing with empty string.
Before change the meaning was similar to is_null.
If you used is_empty for text types with intention of comparing with null, please replace is_empty -> is_null, is_not_empty -> is_not_null in saved query values.
If you used JsonLogic for saving, you need to replace {"!": {"var": "your_field"}} -> {"==": [{"var": "your_field"}, null]} and {"!!": {"var": "your_field"}} -> {"!=": [{"var": "your_field"}, null]}.

Migration from v1 to v2

From v2.0 of this lib AntDesign is now optional (peer) dependency, so you need to explicitly include antd (4.x) in package.json of your project if you want to use AntDesign UI.
Please import AntdConfig from react-awesome-query-builder/lib/config/antd and use it as base for your config (see below in usage).
Alternatively you can use BasicConfig for simple vanilla UI, which is by default.
Support of other UI frameworks (like Bootstrap) are planned for future, see Other UI frameworks.

Contributing

Code Contributing

This project exists thanks to all the people who contribute. [Contribute].

Financial Contributing

Become a financial contributor and help us sustain our community. [Contribute]

If you mention in an GitHub issue that you are a sponsor, we will prioritize helping you.

As a sponsor you can ask to implement a feature that is not in a todo list or motivate for faster implementation.

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

License

MIT. See also LICENSE.txt

Forked from https://github.com/fubhy/react-query-builder

react-awesome-query-builder's People

Contributors

afeedhshaji avatar alphazhe avatar apkawa avatar danyrojj avatar dependabot[bot] avatar derkobe avatar fernandobd42 avatar fubhy avatar jagzmz avatar lbrdar avatar linell avatar mujuni88 avatar mzrt avatar nardove avatar nikhilsarvaiye avatar pedroamcoelho avatar petermoresi avatar pstanize-nht avatar ravikirandn avatar ravipatil1982 avatar remejuan avatar rhallerman avatar robinbullock avatar ruzz311 avatar shaimo avatar spetsmash avatar tagorecaue avatar tk-o avatar ukrbublik avatar vvf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-awesome-query-builder's Issues

Warning: Failed prop type: Invalid prop `children1` of type `Map` supplied to `Item`, expected instance of `OrderedMap`.

Warning: Failed prop type: Invalid prop `children1` of type `Map` supplied to `Item`, expected instance of `OrderedMap`.

For anyone who ever faces the above warning after converting the tree output using fromJS from Immutable, you can solve it by doing the following:

function fromJSOrdered(js){
  return typeof js !== 'object' || js === null ? js :
    Array.isArray(js) ? 
      Immutable.Seq(js).map(fromJSOrdered).toList() :
      Immutable.Seq(js).map(fromJSOrdered).toOrderedMap()
}

Reference: https://github.com/facebook/immutable-js/wiki/Converting-from-JS-objects#custom-conversion

Allow either Immutable or plain json object on import

Immutable strings aren't exactly the best transport for doing any type of AST eval on the backend. So in order to support a backend eval as well as frontend initialization, you would need to store a tuple of a regular json representation as well as the immutable representation (wasteful), or write a recursive fold over the json -> immutable representation. The former is a bad idea for a few reasons, so if you're just left with the latter, why not just support that at a library level?

I generally prefer language level persistent immutable data structures, but for a language like JS that doesn't have it, it seems like a much better idea to enforce immutability internally (if at all), and to allow the option to expose those internals when requested

Typing invalid values fails quietly

typing something that doesn't make sense into the query builder makes it fail quietly.

Perhaps we could add an actual error message, disallow invalid inputs, or just in some way tell the user what happened

querybuilder form elemnts hides onclick or onchange of other form elemnts on the page

I have other form elements like drop down, check box etc present on the page along with query builder.. If i have multiple row visible with query builder with data in it & if i click on other form elements which are not part of query builder then all query builder row disappear and query string becomes empty.
I noticed that in my onchage function i am using this.setState({someFlag :true})
if i comment this.setState({someFlag :true}) code then above issue does not happen, but i need
use setState inside my function.

Can you please help me on this issue.

reset query Conds and hidden Buttons for simple query

@ukrbublik Hello, thanks for your work. I'm developing a big data center. So the query conditions may be very complex. I haven't found how to reset all conditions, just like this:
reset
What's more?Is it possible to hide all the add, add group,and ,or, del Buttons for just a simple search box?
searchonly
pls give me some suggestion.

Select[mode] deprecation warning

Thanks for this awesome library! We're seeing a deprecation warning in the console when using the select widget:

browser.js?3a0d:49 Warning: `Select[multiple|tags|combobox]` is deprecated, please use `Select[mode]` instead.

Can follow up with a PR later.

setDefaultFieldAndOp:true no longer updates query or widget.

Hello ,
I ran into some weird issue when trying to set setDefaultFieldAndOp to true. while it initializes the rule correctly with the correct Field & Operator. updating the value doesn't reflect in the input or the query unless you change the operator to something else ().

You can easily Reproduce the issue by cloning a fresh clone and changing setDefaultFieldAndOp to true. and add any defaultField for example name2.

I am suspecting the issue is originating from "valueType" being initialized with an object and not an array. but i am not sure where to go from there. So any help would be apprechiated.
Thanks

API for add rule

Hey, this library looks like a great fit for my project!

I am however unsure of whether there exists any functionality for calling add rule externally, like from a separate meny in my webapp. Would this be something that could be inserted into Query as a value?

I have read the example code and the github issues. My apology if this question / functionality has already been covered.

ERROR in ./node_modules/antd/lib/time-picker/style/index.js

My webpack is failing:

Module not found: Error: Can't resolve 'style' in path'

BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.
You need to specify 'style-loader' instead of 'style',
see https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed
 @ ./node_modules/antd/lib/time-picker/style/index.js 5:0-23
 @ ./node_modules/antd/lib/date-picker/style/index.js
 @ ./node_modules/react-awesome-query-builder/build/npm/lib/components/widgets/Number.js
@ ./node_modules/react-awesome-query-builder/build/npm/lib/components/widgets/index.js
@ ./node_modules/react-awesome-query-builder/build/npm/lib/index.js

Underscore in string queries

Is there any reason why there's an underscore prepended to string queries. In my implementation, there is a single underscore. In the demo implementation, there are 2 underscores.

If this is a bug, I'll look into it and submit a PR, but if there's a reason I'm unaware of, feel free to let me know.

Thanks for creating this neat little wrapper!

screen shot 2018-11-05 at 9 35 02 am

screen shot 2018-11-05 at 10 01 33 am

How do I avoid nested fields labels being together ?

A structure like this:
screen shot 2018-12-28 at 17 57 03

Ends up causing a weird effect:

screen shot 2018-12-28 at 18 00 59

This effect will be undercovered if you have simple fields placed first... The problem is that fields is an object and object's property order is a complex matter :)

Is there any setting to avoid this behaviour ? Is there a possibility to pass an array as fields so we can have order?

Best regards

$elemMatch

Hi,

For the MongoDB support, do you have a way to customise the queries? jQuery-querybuilder has an event you can hook into which allows us to utilise $elemMatch.

Thanks

Dynamic Config Possible?

Hi. I've been playing around with this. It seems very well done. Looks nice and very flexible and functional.
One problem I'm having is that I don't see an obvious way to dynamically load fields. The config is a full-blown javascript file. If I understand correctly, then this has to be compiled/bundled by webpack.
I'm new to react, webpack, etc, so maybe I just don't understand it well enough.
I need the 'fields' portion of the config file to be dynamically generated at load time. Is there an easy way to do this?
I will have potentially hundreds of fields and they will change depending on who's looking at it.
Thanks

Add custom table to fields configuration

My end goal is that I want to be able to query two tables from the same heading in the query builder. As an example, right now I've got something like this:

    members: {
      label: 'Members',
      type: '!struct',
      subfields: {
        subname: {
          type: 'number',
          operators: ['equal'],
        },
        members_count: { // reference aggregates table
          label: 'Count',
          type: 'number'
        }
      }
    }

Right now this would generate members.subname and members.members_count, but I'd like to have the option to set something like tableName (or something more generic, if you can think of it) so that it'd generate aggregates.members_count while still showing up as one group in the builder.

screen shot 2018-01-04 at 4 34 52 pm

Is there a way to deserialize a saved query and bind to the query Builder

Lets say i have created a query using the query builder with set of fields/operators/values and saved it(JSON) to storage. On my next visit(refresh) to the UI page i want to recreate the UI with all controls(fields/operators/values) with specific values i saved from the saved query in storage with the specific previous values selected.

Multi-tiered or nested json?

Does the builder support multi-tiered feature Where the first drop down opens another select box with 2nd drop down options?? Basically like a nested JSON.

Something like this?

image

how to update fields data from database at <Query> component?

Hi,I like you component.I want to update field data from database at component,But
exception:


react-dom.development.js:244 Uncaught TypeError: Cannot read property 'type' of undefined
    at _validateValue (tree.js:357)
    at setValue (tree.js:533)
    at tree.js:635
    at dispatch (createStore.js:165)
    at Object.setValue (stuff.js:28)
    at Object.RuleContainer._this.setValue (RuleContainer.js:73)
    at WidgetContainer._this._setValue (WidgetContainer.js:98)
    at Object.NumberWidget._this.handleChange [as onChange] (Number.js:68)
    at Object.setValue (mixin.js:140)
    at Object.onBlur (mixin.js:93)
    at HTMLUnknownElement.callCallback (react-dom.development.js:104)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:142)
    at Object.invokeGuardedCallback (react-dom.development.js:191)
    at Object.invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:205)
    at executeDispatch (react-dom.development.js:470)
    at executeDispatchesInOrder (react-dom.development.js:492)
    at executeDispatchesAndRelease (react-dom.development.js:590)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js:601)
    at forEachAccumulated (react-dom.development.js:571)
    at runEventsInBatch (react-dom.development.js:732)
    at runExtractedEventsInBatch (react-dom.development.js:741)
    at handleTopLevel (react-dom.development.js:4198)
    at batchedUpdates (react-dom.development.js:12510)
    at batchedUpdates (react-dom.development.js:1943)
    at dispatchEvent (react-dom.development.js:4279)
    at interactiveUpdates (react-dom.development.js:12565)
    at interactiveUpdates (react-dom.development.js:1962)
    at dispatchInteractiveEvent (react-dom.development.js:4256)

my query config:
fields:{},
other config is not changed from demo,


<Query
                       {...query_config}
                       fields={this.state.from_db_fields}
                      //you can pass object here, see treeJSON at onChange
                      //value=transit.fromJSON(treeJSON)
                          get_children={this.getChildren} />


this.state.from_db_fields had data from database.
please help .
how to update fields data from database at component?
Thanks your see!

Suggestions for Accessibility

I am running into accessibility problems using a screen reader because this library depends on Ant Design (see here: ant-design/ant-design#13198)

Has anyone come up with any workarounds to make the components listed accessible via screen reader?

Thanks!

Bundling issue

So I'm running into an issue with webpack when I bundle this component in with a module.

This is the error I get out on the browser:

621:1 Uncaught Error: Module build failed: 
@import "./themes/default";
@import "./core/index";

^
      File to import not found or unreadable: ./themes/default.
Parent style sheet: stdin
      in C:\vso-git\myapp\node_modules\antd\lib\style\index.less (line 1, column 1)

here's what I get in the CLI:

ERROR in ./~/css-loader!./~/less-loader/dist/cjs.js!./~/sass-loader/lib/loader.js?{"includePaths":["./AdvancedSearch/Adv
ancedSearch/Content/Modules/AdvancedSearch","C://vso-git//myapp//host//Content"]}!./~/antd/lib/style/index.les
s
Module build failed:
@import "./themes/default";
@import "./core/index";

^
      File to import not found or unreadable: ./themes/default.
Parent style sheet: stdin
      in C:\vso-git\myapp\node_modules\antd\lib\style\index.less (line 1, column 1)
 @ ./~/antd/lib/style/index.less 4:14-146
 @ ./~/antd/lib/date-picker/style/index.js
 @ ./~/react-awesome-query-builder/build/npm/lib/components/widgets/Number.js
 @ ./~/react-awesome-query-builder/build/npm/lib/components/widgets/index.js
 @ ./~/react-awesome-query-builder/build/npm/lib/index.js
 @ ./AdvancedSearch/AdvancedSearch/App/Modules/AdvancedSearch/viewmodels/QueryBuilderEx.es6
 @ ./~/babel-loader/lib?{"presets":["babel-preset-es2015","react","stage-3"]}!./AdvancedSearch/AdvancedSearch/App/Module
s/AdvancedSearch/viewmodels/AdvancedSearch.es6
 @ ./AdvancedSearch/AdvancedSearch/App/Modules/AdvancedSearch/viewmodels/AdvancedSearch.es6
 @ multi ./AdvancedSearch/AdvancedSearch/App/Modules/AdvancedSearch/viewmodels/AdvancedSearch.es6 ./AdvancedSearch/Advan
cedSearch/App/Modules/AdvancedSearch/viewmodels/AdvancedSearch.html

Now this could be an issue with antd, as the error is clearly coming from that library. And there's a bunch of other less style issues that I am getting this is just 1 / 6 errors I'm getting all pointing to the less styles in antd design.

I have a less-loader in my webpack below is my configuration:

    module: {
        rules: [{
            test: /\.es6|.jsx|.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: { presets: ['babel-preset-es2015', 'react', 'stage-3'] } //stage-3 does the polyfilling for '...' syntax
        }, {
            test: path.resolve(moduleExportPath),
            exclude: /node_modules/,
            use: [{
                loader: 'expose-loader',
                options: `__${type}_${dmxModule}`
            }, {
                loader: 'babel-loader',
                options: { presets: ['babel-preset-es2015', 'react', 'stage-3'] } //stage-3 does the polyfilling for '...' syntax
            }]
        }, {
            test: /\.html$/,
            loader: 'custom-knockout-template-loader!html-loader'
        }, {
            test: /\.(scss|css|less)$/,
            //include: path.resolve(__dirname, './host/Content'),
            //exclude: /node_modules/,
            use: [{
                loader: "style-loader" // creates style nodes from JS strings
            }, {
                loader: "css-loader" // translates CSS into CommonJS
            }, {
                loader: "less-loader",
            }, {
                loader: "sass-loader", // compiles Sass to CSS
                options: {
                    includePaths: [moduleCssRootFile, path.resolve(__dirname, './host/Content')]
                }
            }]
        }, {
            test: /\.json$/,
            loader: 'json-loader',
        }],
        loaders: [{
            test: /exporting/, loader: 'imports?highstock'
        }, {
            test: /highcharts.modules.treemap/, loader: 'imports?highstock,highcharts.modules.heatmap'
        }, {
            test: /highcharts.modules.heatmap/, loader: 'imports?highstock'
        }]
    }

So I could be using the less loader incorrectly here. If so let me know what I should do I've tried a few different approaches. Including how you configured your webpack config here: https://github.com/ukrbublik/react-awesome-query-builder/blob/master/webpack.config.js

Don't run in IE

Awesome query builder does not render in Internet Explorer.

I get "Object doesn't support property in method 'remove'" on stuff.js (45,3)

The sample also fails (with a different error in this case).

Restore from saved result will convert list of value to single value.

I have a configured a in operator which allows a list of values.

select_in: {
    label: 'in',
    labelForFormat: 'IN',
    formatOp: (field, op, values, valueSrc, valueType, opDef, operatorOptions, isForDisplay) => {
      if (valueSrc === 'value') {
        return `${field} IN (${values.join(', ')})`
      } else {
        return `${field} IN (${values})`
      }
    },
    reversedOp: 'select_not_in'
  }

Say, I have stored a select_in item have values [1, 2, 3] in my savedTree.

When restore form the tree.

        <Query
          {...config}
          value={savedTree}
          onChange={this.onChange}
          get_children={this.getChildren}
        > </Query>

The constructor of ConnectedQuery at line will call the validateTree.

this.validatedTree = this.validateTree(props, props.config, props.tree);

And then goto the line:

const operatorCardinality = newOperator ? defaultValue(newOperatorConfig.cardinality, 1) : null;

will set operatorCardinality to 1 for my select_in operator. And the the follow line use operatorCardinality to cut my list of 3 values to list of only 1 value:

newValue = new Immutable.List(Array.from({length: operatorCardinality}, (_ignore, i) => {

The the newValue will will be [1].

Update to latest version of antd

This lib is using with antd v2.12.2 which is bit aged. Some of my components rendered differently after this library being used. I assume this is cause by the older version of antd.

SQL format Util?

Is there already something available (or) something on the roadmap to get the SQL equivalent of the query
that can become the WHERE clause and passed to the database.

Could be an extension to the human string format queryString

Can't Install on Windows?

Hi. Project looks great. I wanted to play with it, but can't get past the first step.. "npm install".

It's failing on "rm -rf build/npm && babel -d build/npm/lib ./modules && cp README.md build/npm...."

I'm not very familiar with npm, but it looks like if I want to run the examples, I would need to do some hacking to convert *nix script code to Windows?

readme

  • .query-builder-container for sortable in scrollable container
  • config

New type in query builder?

Is there any way to add new type other than existing? Like for between query builder I would like add slider control (other that two input controls), for that I tried to add new Type but its not working for my.
Or is there any other way to add Slider widget in existing code?

Messing up the styles in an existing project

I have a project and I wanted to integrate this query builder into it, but it messes up all my styles. Can anyone help me to find a way to "isolate" query builder own styles from the rest of the styles from the application?

Bad validation of multiselect values when using redux and immutable-js

Hey @ukrbublik,

So I have been using your library (with redux) for a while now and its been working great! However, I was recently asked to attempt to add multiselect, and found some issues with the MultiSelectWidget when storing the querytree in redux (or probably any other storage).

What happens
My program takes the onChange querytree from Query and stores them in redux, then uses this tree to reinstantiate Query. However, when I try to initialize Query with a querytree containing MultiSelectWidgets, their values are immediatly reset.

What I think causes this
I believe that I have located the bug in the function _getNewValueForFieldOp in modules/stores/tree.js. After doing some console.log testing, I can see that this if-sentence does not have an else statement, and in my case of trying to add a value to a MultiSelectWidget, the newValue is not set and is thus reset to undefined. The problem is not here. Firstly the value is in the wrong format (immutable list rather than normal list), secondly this if triggers and sets the value to invalid.

debug

Whats in the image
Here are some console.logging I did. It shows the currentval and return value of this if sentence. As you can see, the currentval is at one point a List [ List [] ], which doesn't run properly.

What I thought I could do
I kinda already promised to deliver this functionality, so I would like to create a pull request, mb tomorrow or something. I can however not be 100% sure that I dont make any breaking changes, since this is core functionality. So if you could help me out with checking if my pull request is good that would be great :)

TL;DR: I think I found a bug, will make PR, please help to ensure its good

EDIT: update with more debugging info

Building Issue

I am getting below error after importing component in application

node_modules\antd\lib\style\index.css:12
SyntaxError: Unexpected token {
at createScript (vm.js:56:10)
at Object.runInThisContext (vm.js:97:10)
at Module._compile (module.js:542:28)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object. (node_modules\antd\lib\col\style\css.js:3:1)

queryBuilderFormat

Is there a way to use the result of queryBuilderFormat to repopulate the querybuilder in the value prop?

Can't Install With NPM

I am getting the below error. I have already antd installed in a project .


$ npm i react-awesome-query-builder
[email protected] /Users/umutguncan/netionant
└─┬ [email protected]
  └─┬ [email protected]
    ├── [email protected]
    ├── [email protected]
    ├── [email protected]
    ├─┬ [email protected]
    │ └── [email protected]
    ├─┬ [email protected]
    │ └── [email protected]
    ├── [email protected]
    ├── [email protected]
    ├── [email protected]
    ├── [email protected]
    ├── [email protected]
    ├── [email protected]
    ├── [email protected]
    ├── [email protected]
    └── [email protected]

npm WARN [email protected] requires a peer of webpack@1 || 2 || ^2.1.0-beta || ^2.2.0-rc but none was installed.

Setting for "Add rule"

It would be great to have a setting that shows/hides "Add rule" button.

User case, I would like to show a "ready-only" mode where it shows the rules but does not allow to make changes. I understand that there will need to be other things to make it really readonly, but this could be a start.

If you're ok with this proposal, I can create a PR

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.