0

On an Angular application I'm using the QueryBuilder Component with a Column Template. In the column template I programmed a Multiselect that consume an endpoint to retrieve data, and this endpoint return 5 elements, so, each time I type a new letter in the filter of the multiselect, the endpoint will be consumed.

RuleConfiguration.component.ts

customTemplate(api: string = "", fields: {text: string, value: string}): TemplateColumn {
    return {
      create: () => {
        let customId = util.createGuidRandom()

        const element = document.createElement('input');
        element.setAttribute('customid', customId)

        this.multiSelectDataManagers[customId] = new DataManager({url: environment.serverUriApi + api})
        this.multiSelectQueries[customId] = new Query().addParams('searchText', '').addParams('limit', '5')

        return element;
      },
      destroy: (args: { elementId: string }) => {
        let multiselect: MultiSelect = getComponent(document.getElementById(args.elementId), 'multiselect') as MultiSelect;
        if (multiselect) { multiselect.destroy(); }
      },
      write: (args: { elements: Element; values: string[] | string; operator: string }) => {
        let texto = args.elements.outerHTML
        let regex = /customid="([^"]+)"/;
        let match = texto.match(regex);
        let multiSelectId = match[1];

        if (['in', 'notin'].indexOf(args.operator) > -1) {
          this.multiSelectObjs[multiSelectId] = new MultiSelect({
            dataSource: this.multiSelectDataManagers[multiSelectId] ,
            value: args.values as string[],
            mode: 'Box',
            query: this.multiSelectQueries[multiSelectId],
            allowFiltering: true,
            filtering: (e) => {
              this.multiSelectQueries[multiSelectId] = new Query().addParams('searchText', e.text).addParams('limit', '5');
              e.updateData(this.multiSelectDataManagers[multiSelectId], this.multiSelectQueries[multiSelectId])
            },
            fields: fields,
            change: (e) => {
              this.qryBldrObj.notifyChange(e.value, e.element);
              this.onQueryBuilderChange.emit({form: {sql: this.getSql(), json: this.getJson()}, type: 'rules'})
            },
          });
          this.multiSelectObjs[multiSelectId].appendTo('#' + args.elements.id);
        } 
      },
    };
  }

RuleConfiguration.component.html

<div class="container-fluid" style="background-color: white">

  <div class="control-section">
    <div class="col-lg-8 control-section">
      <ejs-querybuilder
        id="querybuilder"
        #querybuilder
        cssClass="row"
        [columns]="filter"
        width="100%"
        locale="es-PE"
      >
      </ejs-querybuilder>
    </div>
  </div>
</div>

The component is working fine, I can retrieve sql and json statements from the query builder, but... when I import data that I stored previously and put in the QueryBuilder, the items that I retrieve from the endpoint was not selected. Example:

Data to import:

{
    "condition": "and",
    "rules": [
        {
            "label": "Empleado",
            "field": "CodeVendor",
            "type": "string",
            "operator": "in",
            "value": [
                "000436",
                "001055"
            ]
        },
        {
            "label": "Compañia",
            "field": "CompanyRUC",
            "type": "string",
            "operator": "in",
            "value": [
                "000013"
            ]
        }
    ]
}

RuleConfiguration.component.ts

@ViewChild('querybuilder') qryBldrObj: QueryBuilderComponent;

ngOnInit() {
      this.qryBldrObj.setRules(JSON.parse(this.activeBreakRule.LogicalConditionJson) as RuleModel)
}

This example does not work, because the values that I have from CodeVendor and CompanyRUC in the json do not exist in the multiselect, since these are fetched remotely, is there a way to import a json in a query builder that use a multiselect template to retrieve remote data?

Jorge Ramón
  • 141
  • 1
  • 1
  • 8

1 Answers1

0

We have validated your reported query and understand that you are trying to set the Multi-select component value through the query builder rule. We suspect that, while fetching the data source for the multi-select component through the data manager, it does not contain the given value in the query builder rule. So it does not display the value in the multi-select control of the query builder.

We have prepared the sample based on your requirements. Refer to the below code snippet and sample link.

[app.component.ts]:

  create: () => {

    this.data = new DataManager({

      url: "http://controller.com/api",

      adaptor: new WebApiAdaptor

    });

    return createElement('input', { attrs: { 'type': 'text' } });

  },

  write: (args: { elements: Element, values: string[] | string, operator: string }) => {

    let multiSelectObj: MultiSelect = new MultiSelect({

      dataSource: this.data,

      value: args.values as string[],

      fields: { text: 'CustomerID', value: 'OrderID' },

      query: new Query().select(['CustomerID', 'OrderID']).take(5),

      allowFiltering: true,

      mode: 'Box',

      placeholder: 'Select a Number',

      change: (e: any) => {

        this.qryBldrObj!.notifyChange(e.value, e.element);

      }

    });

    multiSelectObj.appendTo('#' + args.elements.id);

  }

};

If you set beyond the preselect value into a multiselect component, you need to write the code in your local service end to filter the data, like in the below code and sample.

// GET: api/Orders

    [HttpGet]



    public object Get()

    {

        var queryString = Request.Query;

        var data = OrdersDetails.GetAllRecords().ToList();

        int take = Convert.ToInt32(queryString["$top"]);

       string filter = queryString["$filter"];  //filtering

        if (filter != null) // to handle filter opertaion

        {

            var newfiltersplits = filter;

            var filtersplits = newfiltersplits.Split('(', ')', ' ');

            var filterfield = filtersplits[0];

            var filtervalue = filtersplits[2];



            if (filterfield == "OrderID")

            {



               return data = (from cust in data

                        where cust.OrderID.ToString() == filtervalue.ToString()

                        select cust).ToList();

            }

        }

        return data.Take(take).ToList();

    }

Sample link: https://www.syncfusion.com/downloads/support/directtrac/general/ze/Solution11812133079