Set the name of the required input for Batch in query widget using new conditions

Hi,

We are using Webix Pro Edition (Webix UI v.10.2.1) , Is there any option to set the name of the required input for Batch as ‘select’ or ‘combo’ or ‘richselect’ or ‘richtext’?.

https://snippet.webix.com/awefqd96

Only ‘text’, ‘number’, ‘date’ working as expected

Ex:
var maxLength = {
id: “max-length”,
value: “Max Length”,
batch: “richselect”,
handler: (a, v) => a.length <= v,
};

Other than ‘text’ , above mentioned batch values are not working for me in Query widget,

Old Sample:

image
We have the same functionality in lower version (Webix UI v.7.3.5) with querybuilder as like below given snippet , FYI.

var coulmnCountEditor = { view: “richselect”, options: [“Column Count”] };
var associatedFileListEditor = { view: “richselect”, options: $scope.associatedFileLists };
var recordDelimiter = { view: “richselect”, options: [“Header Delimiter”] };

$scope.operators = [
{ view: “select”, name: “equal”, id: “RecordColumnCount”, type: { “RecordColumnCount”: coulmnCountEditor } },
{ view: “select”, name: “contains”, id: “AssociatedFileList”, type: { “AssociatedFileList”: associatedFileListEditor } },
{ view: “select”, name: “equal”, id: “RecordDelimiter”, type: { “RecordDelimiter”: recordDelimiter } }
]

webix.ui({
container: “rule-builder-control”,
view: “querybuilder”,
id: “querybuilder”,
fields: $scope.fields,
filters: $scope.operators,
maxLevel: $scope.maxlevel,
inputMaxWidth: 350
});

So we need to achieve same functionality using query widget.

Thanks

Hello @vinoshmani,

As querybuilder is a complitly diffrent widget, which was based not on the Webix Jet (as cirrent view: query), previous functionality is not expected to work.

In order to implement the functionality you described in a Query, Query customization is requested. It is necessary to rewrite the CreateFilter function of FilterView with the:

conditions.map(id => {
			if (id === 'richselect_name') {
				return 
      id: "Name",
      value: "Richselect Name",
      batch: "richselect_name",
      handler: function(a, b) {
        return a == b;
      },
      on: {
		onChange: function() {
			const filter = this.queryView("filter", "parent");
         	filter.applyFilter();
		}
      }
  }
			}
			return id;
		})

Please, check out the snippet with the example: Code Snippet

Hi Team & NatashaS,
Good day,

From the code snippet sample you have shared in your reply, We need some input. What is ‘query’ while have the CustomFilter class.
CustomFilter extends query.views.filter

Because query is undefined in my end,




image

We have reference of the require("@xbs/query") inside webix.ready as well

Below my react component code for reference:

import React, { Component } from "react";

import ReactDOM from "react-dom";

import * as webix from "@xbs/webix-pro";

import "@xbs/webix-pro/webix.css";

import "@xbs/query/codebase/query.css";

class QueryBuilder extends Component {

    constructor(props) {

        super(props);

        this.uiContainer = React.createRef();

    }

    handleSaveQuery = () => {

        if (this.ui) {

            return this.ui.getState().value; // Get the generated query

        }

    };

    render() {

        return <div ref={this.uiContainer} style={{ height: "100%" }} ></div>;

    }

    componentDidUpdate() {

        const container = ReactDOM.findDOMNode(this.uiContainer.current);

       

            webix.ready(() => {

                require("@xbs/query");

                if (this.ui) {

                    this.ui.destructor();

                    this.ui = null;

                }

                               

                const richselectConditions = {

                    id: "Name",

                    value: "Richselect Name",

                    batch: "richselect_name",

                    handler: function(a, b) {

                      return a == b;

                    },

                    on: {

                      onChange: function() {

                          const filter = this.queryView("filter", "parent");

                           filter.applyFilter();

                      }

                    }

                };

       

                const inputs = [

                    'text',

                    {

                        view: 'richselect',

                        options:[

                            'Alex',

                            'Diana',

                            'Max'

                        ],

                        moveTitle: false,

                        batch: 'richselect_name',

                        title: (obj) => obj.value,

                        on: {

                            onChange: function() {

                                const filter = this.queryView('filter', 'parent');

                                filter.applyFilter();

                            }

                        }

                    },

                ];

            class CustomFilter extends query.views.filter {

                    CreateFilter(field, type, format, conditions, place) {

                      const newConditions = conditions.map(id => {

                          if (id === 'richselect_name') {

                              return richselectConditions;

                          }

                          return id;

                      });

                      const ui = {

                          view: 'filter',

                          localId: 'filter',

                          inputs: inputs,

                          conditions: newConditions,

                          field,

                          mode: type,

                          template: (o) => {

                              let str = o[field];

                              const parser = o.format || (type == 'date' ? webix.i18n.dateFormatStr : null);

                              if (parser) str = parser(str);

                              return str;

                            },

                          margin: 6,

                      };

             

                      const filter = webix.ui(ui, place);

                      const data = this.app.getService("backend").data(field);

                      filter.parse(data);

                      return filter;

                    }

                }

                const queryUI = webix.ui({

                    view: "query",

                    id: "query",

                    maxLevel: 3,

                    width: 340,

                    override: new Map([[query.views.filter, CustomFilter]]),

                    fields: this.props.field,

                    value: this.props.value,

                    simple: this.props.simpleMode,

                    container,

                });

                this.ui = queryUI;

            });

        this.resObserver = new ResizeObserver(() => {

            if (this.ui) this.ui.adjust();

        });

        this.resObserver.observe(container);

    }

    componentWillUnmount() {

        const container = ReactDOM.findDOMNode(this.uiContainer.current);

        if (this.ui) {

            this.ui.destructor();

            this.ui = null;

        }

        if (this.resObserver) {

            this.resObserver.disconnect();

        }

    }

}

export default QueryBuilder;

Good day @vinoshmani ,

As far as I can see, you are facing an issue with a query reference: require("@xbs/query");

To use this module for the later customizations, you could:

  1. Assign imported module to a variable, for example:
const query = require("@xbs/query");
class CustomFilter extends query.views.filter {
...
}

or

  1. You can use the ProvidePlugin from Webpack to define Webix/Query/Other widgets globally.

The second variant is described in our demo of using Complex widgets in React: GitHub - webix-hub/react-demo-complex: This demo shows how to init Webix complex widgets in React components.
The Webpack config can be found in the config folder (see https://github.com/webix-hub/react-demo-complex/blob/97b76fc2eb45d483c9d63935588fe106347c3ae4/config/webpack.config.js#L750). Here, the core library is available as a global script - in such cases, you can use the import (or require) keyword to import modules in the upper scope.

If you are using create-react-app, you can call the yarn eject command to access the Webpack config.

Hi MariyaDemy & Team,
Good day ,

Based on the above input , we have added the CustomFilter with ‘richselect_name’ batch. These changes are good and working as expected. But we are facing some issue for batch ‘none’ when we use the CustomFilter.

var recordDelimiter = {

            id: "equal",

            value: "equal",

            batch: 'richselect_name',

            handler: function (a, b) {

                return a === b;

            },

            on: {

                onChange: function () {

                    const filter = this.queryView("filter", "parent");

                    filter.applyFilter();

                }

            }

        };
  1. Point 1:

We are facing some issue for batch ‘none’ when we use the CustomFilter. And parallelly with out this custom filter batch ‘none’ working as expected. I have described the issue ,
image
image


Note: Batch ‘text’ conditions are working as expected. But batch ‘none’ type conditions are not working when we use the CustomFilter. (In Previous chat i have shared the code for reference , fyi). Please do the needful.
Thanks & Regards,
Vinosh M

Hi Team,
Good day,

Above mentioned ‘CustomFilter’ with ‘none’ batch scenario i have added snippet sample including multiple batch type.
https://snippet.webix.com/95kw988m

Thanks & Regards,
Vinosh M

Hello @vinoshmani ,

In the suggested by NatashaS solution we redefine the possible filter inputs: Code Snippet (check 48 and 17 code lines). So, while the default set have an input of type “none”, the customFilter misses it. So, to avoid the error you need to add:

const inputs = [
      'text',
      'none',
      {
          view: 'richselect',
         ...
}]
1 Like