Query widget filter

1239
6
Jump to solution
06-18-2019 05:03 AM
AlbertoCañivano
New Contributor III

I want to pass a value to the Query widget from a URL link.

I put that url inside Query widget_initSelf and using urlToObject(url) would get the value of the field I want to filter

_initSelf:function(){
        var queries = this.config.queries;

        if(queries.length === 0){
          html.setStyle(this.tasksNode, 'display', 'none');
          html.setStyle(this.noQueryTipSection, 'display', 'block');
          return;

          } else {
          var myObject= urlUtils.urlToObject("http://url.com?PROPIEDAD_ID=34005")         
          console.log(myObject.query.PROPIEDAD_ID)             
          }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I would like to know in which part of the widget.js I should pass the object I get to make the filter.

My goal is that when this url does not have any filtering value (PROPIEDAD_ID is empty) the Query widget will be used with all the records (which is how I have it configured right now);
While when this url has a query value, be able to pass the object as a filter to the Query (PROPIEDAD_ID is one of the fields of my geometry) and appear filtered and zoomed to the new operational layer created.

Thank you!

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Alberto,

   Pass more than one value using a comma in the url (i.e. /webappbuilder/?id=27&PROPIEDAD_ID=50,100)

I have now made sure that if you have only on query setup it does not care about the name of the query.

You will be responsible for your requirement of querying everything if there is not a PROPIEDAD_ID in the url (I can't do everything for your ).

Here is how to setup the query for a number field and a list of comma separated values.

Here are the code changes to the Widget.js

_initSelf changes (lines 58 - 61).

      _initSelf:function(){
        var queries = this.config.queries;

        if(queries.length === 0){
          html.setStyle(this.tasksNode, 'display', 'none');
          html.setStyle(this.noQueryTipSection, 'display', 'block');
          return;
        } 

        //create query tasks
        array.forEach(queries, lang.hitch(this, function(singleConfig, index){
          var defaultIcon = this.folderUrl + "css/images/default_task_icon.png";
          queryUtils.dynamicUpdateConfigIcon(singleConfig, defaultIcon);
          var name = singleConfig.name;
          var strTr = '<tr class="single-task">' +
            '<td class="first-td"><span class="task-icon"></span></td>' +
            '<td class="second-td">' +
              '<div class="list-item-name task-name-div"></div>' +
            '</td>' +
          '</tr>';
          var tr = html.toDom(strTr);
          var queryNameDiv = query(".task-name-div", tr)[0];
          queryNameDiv.innerHTML = name;
          html.place(tr, this.tasksTbody);

          var iconNode = query("span.task-icon", tr)[0];
          var icon = singleConfig.icon;

          if (icon) {
            var size = 16;
            var symbolNodeStyle = null;
            var isImgType = icon.url || icon.imageData;

            if (isImgType) {
              icon.setWidth(size);
              icon.setHeight(size);
            } else {
              symbolNodeStyle = {
                width: size + 1,
                height: size + 1
              };
              icon.setSize(size);
            }

            var symbolNode = jimuSymUtils.createSymbolNode(icon, symbolNodeStyle);
            html.place(symbolNode, iconNode);
          }

          tr.taskIndex = index;
          tr.singleConfig = singleConfig;
          if(index % 2 === 0){
            html.addClass(tr, 'even');
          }else{
            html.addClass(tr, 'odd');
          }
        }));

        var params = this.mapManager.urlParams;
        if(params.PROPIEDAD_ID){
          queries[0].filter.parts[0].valueObj.value =  params.PROPIEDAD_ID.split(',');
        }
      },

_onClickTaskTr changes (lines 53 - 56).

      _onClickTaskTr: function(tr){
        //this._getLayerInfoAndServiceInfo(tr).then(lang.hitch(this, function(response){
        this._getLayerInfoAndRelationshipLayerInfos(tr).then(lang.hitch(this, function(response){
          var layerInfo = response.layerInfo;
          var layerObject = response.layerObject;
          //var serviceInfo = response.serviceInfo;
          var relationshipLayerInfos = response.relationshipLayerInfos;
          var relationshipPopupTemplates = response.relationshipPopupTemplates;
          tr.singleConfig.objectIdField = jimuUtils.getObjectIdField(layerInfo);
          var popupInfo = this._getPopupInfo(layerInfo, tr.singleConfig);
          if(!popupInfo){
            console.error("can't get popupInfo");
          }
          popupInfo.fieldInfos = queryUtils.getPortalFieldInfosWithoutShape(layerInfo, popupInfo.fieldInfos);
          delete popupInfo.readFromWebMap;
          //now we get all layerDefinitions and popupInfos
          //we prepare currentAttrs here
          var currentAttrs = SingleQueryLoader.getCleanCurrentAttrsTemplate();
          currentAttrs.queryTr = tr;
          currentAttrs.config = lang.clone(tr.singleConfig);
          currentAttrs.config.popupInfo = popupInfo; //add popupInfo attribute
          currentAttrs.layerInfo = layerInfo;
          currentAttrs.layerObject = layerObject;
          //currentAttrs.serviceInfo = serviceInfo;
          currentAttrs.relationshipLayerInfos = relationshipLayerInfos;
          currentAttrs.relationshipPopupTemplates = relationshipPopupTemplates;
          currentAttrs.query.maxRecordCount = layerInfo.maxRecordCount || 1000;

          currentAttrs.queryType = queryUtils.getQueryType(layerInfo);

          //after get currentAttrs, we can show task setting pane destroy the old TaskSetting dijit and create a new one
          if (this.currentTaskSetting) {
            this.currentTaskSetting.destroy();
          }
          this.currentTaskSetting = null;
          this._showTaskSettingPane();
          this.currentTaskSetting = new TaskSetting({
            nls: this.nls,
            map: this.map,
            showFilterLabel:this._showFilterLabel,
            criteiraLabel:this.config.criteiraLabel,
            spatialFilterLabel:this.config.spatialFilterLabel,
            currentAttrs: currentAttrs,
            layerInfosObj: this.layerInfosObj,
            onBack: lang.hitch(this, function() {
              this._showTaskListPane();
            }),
            onApply: lang.hitch(this, function(currentAttrs) {
              this._onBtnApplyClicked(currentAttrs);
            })
          });

          var params = this.mapManager.urlParams;
          if(params.PROPIEDAD_ID){
            this.currentTaskSetting._onBtnApplyClicked();
          }

          if (this.currentTaskSetting.canAutoRunning()) {
            this._switchToResultTab();
            //if the task can run without specify other parameters, then we run it automatically
            this.currentTaskSetting.run();
          }

          this.currentTaskSetting.placeAt(this.taskSettingContainer);
        }), lang.hitch(this, function(err){
          console.error("can't get layerInfo", err);
        }));
      },

View solution in original post

0 Kudos
6 Replies
RobertScheitlin__GISP
MVP Emeritus

Alberto,

Here is what you are after (lines 58 - 71 and 125 - 131). This assumes that you have a query named "Parcels" and have more than one query configured in the widget.

      _initSelf:function(){
        var queries = this.config.queries;

        if(queries.length === 0){
          html.setStyle(this.tasksNode, 'display', 'none');
          html.setStyle(this.noQueryTipSection, 'display', 'block');
          return;
        } 

        //create query tasks
        array.forEach(queries, lang.hitch(this, function(singleConfig, index){
          var defaultIcon = this.folderUrl + "css/images/default_task_icon.png";
          queryUtils.dynamicUpdateConfigIcon(singleConfig, defaultIcon);
          var name = singleConfig.name;
          var strTr = '<tr class="single-task">' +
            '<td class="first-td"><span class="task-icon"></span></td>' +
            '<td class="second-td">' +
              '<div class="list-item-name task-name-div"></div>' +
            '</td>' +
          '</tr>';
          var tr = html.toDom(strTr);
          var queryNameDiv = query(".task-name-div", tr)[0];
          queryNameDiv.innerHTML = name;
          html.place(tr, this.tasksTbody);

          var iconNode = query("span.task-icon", tr)[0];
          var icon = singleConfig.icon;

          if (icon) {
            var size = 16;
            var symbolNodeStyle = null;
            var isImgType = icon.url || icon.imageData;

            if (isImgType) {
              icon.setWidth(size);
              icon.setHeight(size);
            } else {
              symbolNodeStyle = {
                width: size + 1,
                height: size + 1
              };
              icon.setSize(size);
            }

            var symbolNode = jimuSymUtils.createSymbolNode(icon, symbolNodeStyle);
            html.place(symbolNode, iconNode);
          }

          tr.taskIndex = index;
          tr.singleConfig = singleConfig;
          if(index % 2 === 0){
            html.addClass(tr, 'even');
          }else{
            html.addClass(tr, 'odd');
          }
        }));

        setTimeout(lang.hitch(this, function(){
          var params = this.mapManager.urlParams;
          if(params.PROPIEDAD_ID){
            var trs = query('.single-task', this.tasksTbody);
            for (child in trs) {
              var node = trs[child];
              var label = node.innerText.trim();
              if (label == 'Parcels'){
                this._onClickTaskTr(node);
                break;
              }
            }
          }
        }), 600);
      },
...
      _onClickTaskTr: function(tr){
        //this._getLayerInfoAndServiceInfo(tr).then(lang.hitch(this, function(response){
        this._getLayerInfoAndRelationshipLayerInfos(tr).then(lang.hitch(this, function(response){
          var layerInfo = response.layerInfo;
          var layerObject = response.layerObject;
          //var serviceInfo = response.serviceInfo;
          var relationshipLayerInfos = response.relationshipLayerInfos;
          var relationshipPopupTemplates = response.relationshipPopupTemplates;
          tr.singleConfig.objectIdField = jimuUtils.getObjectIdField(layerInfo);
          var popupInfo = this._getPopupInfo(layerInfo, tr.singleConfig);
          if(!popupInfo){
            console.error("can't get popupInfo");
          }
          popupInfo.fieldInfos = queryUtils.getPortalFieldInfosWithoutShape(layerInfo, popupInfo.fieldInfos);
          delete popupInfo.readFromWebMap;
          //now we get all layerDefinitions and popupInfos
          //we prepare currentAttrs here
          var currentAttrs = SingleQueryLoader.getCleanCurrentAttrsTemplate();
          currentAttrs.queryTr = tr;
          currentAttrs.config = lang.clone(tr.singleConfig);
          currentAttrs.config.popupInfo = popupInfo; //add popupInfo attribute
          currentAttrs.layerInfo = layerInfo;
          currentAttrs.layerObject = layerObject;
          //currentAttrs.serviceInfo = serviceInfo;
          currentAttrs.relationshipLayerInfos = relationshipLayerInfos;
          currentAttrs.relationshipPopupTemplates = relationshipPopupTemplates;
          currentAttrs.query.maxRecordCount = layerInfo.maxRecordCount || 1000;

          currentAttrs.queryType = queryUtils.getQueryType(layerInfo);

          //after get currentAttrs, we can show task setting pane destroy the old TaskSetting dijit and create a new one
          if (this.currentTaskSetting) {
            this.currentTaskSetting.destroy();
          }
          this.currentTaskSetting = null;
          this._showTaskSettingPane();
          this.currentTaskSetting = new TaskSetting({
            nls: this.nls,
            map: this.map,
            showFilterLabel:this._showFilterLabel,
            criteiraLabel:this.config.criteiraLabel,
            spatialFilterLabel:this.config.spatialFilterLabel,
            currentAttrs: currentAttrs,
            layerInfosObj: this.layerInfosObj,
            onBack: lang.hitch(this, function() {
              this._showTaskListPane();
            }),
            onApply: lang.hitch(this, function(currentAttrs) {
              this._onBtnApplyClicked(currentAttrs);
            })
          });
          var params = this.mapManager.urlParams;
          if(params.PROPIEDAD_ID){
            this.currentTaskSetting.filterParams.partsObj.parts[0].valueObj.value = params.PROPIEDAD_ID;
            var provs = this.currentTaskSetting.filterParams.getValueProviders();
            provs[0].valueProvider.setValueObject(this.currentTaskSetting.filterParams.partsObj.parts[0].valueObj);
            this.currentTaskSetting._onBtnApplyClicked();
          }

          if (this.currentTaskSetting.canAutoRunning()) {
            this._switchToResultTab();
            //if the task can run without specify other parameters, then we run it automatically
            this.currentTaskSetting.run();
          }

          this.currentTaskSetting.placeAt(this.taskSettingContainer);
        }), lang.hitch(this, function(err){
          console.error("can't get layerInfo", err);
        }));
      },‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
AlbertoCañivano
New Contributor III

Robert.

I'm working on the comments you told me.
I have generated a new query called "Parcels", although the version in production should have only one query that shows the filtered value contained in the url or, if there is no value, that shows all the records.

setTimeout(lang.hitch(this, function(){
          
          var myObject= urlUtils.urlToObject("http://url/?PROPIEDAD_ID=603").query          
                    
          if(myObject.PROPIEDAD_ID){
            var trs = query('.single-task', this.tasksTbody);
            for (child in trs) {
              var node = trs[child];
              var label = node.innerText.trim();
              if (label == 'Parcels'){
                this._onClickTaskTr(node);
                break;
              }
            }
          }
        }), 600);‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

...

var myObject= urlUtils.urlToObject("http://url/?PROPIEDAD_ID=603").query       
                    
          if(myObject.PROPIEDAD_ID){
            this.currentTaskSetting.filterParams.partsObj.parts[0].valueObj.value = myObject.PROPIEDAD_ID;
            var provs = this.currentTaskSetting.filterParams.getValueProviders();
            provs[0].valueProvider.setValueObject(this.currentTaskSetting.filterParams.partsObj.parts[0].valueObj);
            this.currentTaskSetting._onBtnApplyClicked();
          }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

the url parameters should be passed to the MapManager and called by this.urlParams. Is that correct?

For this example I have put them in the widget.js.

It doesn't give any error, however the Query widget doesn't filter by the URL parameter and keeps returning 100% of the records.
What can be the cause? Thank you

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Alberto,

   I am not sure why you are hard coding the url. All you have to do is add the parameter to your WAB apps url (i.e. https://localhost:3344/webappbuilder/?id=xx&PROPIEDAD_ID=603).

I have generated a new query called "Parcels"

You can rename it whatever you want as long as you change the code to look for that specific name.

You did setup the query to search for PROPIEDAD_ID field "contains" and "Ask for values" right?

0 Kudos
AlbertoCañivano
New Contributor III

Robert, 

I am not sure why you are hard coding the url. All you have to do is add the parameter to your WAB apps url (i.e. https://localhost:3344/webappbuilder/?id=xx&PROPIEDAD_ID=603).

Thanks for the comment; I wasn't really understanding how Map manager works.
I was trying to see how I could pass more than one value to PROPERTY_ID and make the query with more than one value.
I'm still investigating how to do what I asked you a few days ago.

 

You did setup the query to search for PROPIEDAD_ID field "contains" and "Ask for values" right?

PROPIEDAD_ID is a numerical type field so I do not have the option "contains". The widget is configured with the option "is any of..." and "Ask for values".
I'm realizing that with the code you told me what it looks for and filters is the number of characters that has the PROPIEDAD_ID searched. If I want to search PROPIEDAD_ID = 603; search for 3 characters, for example.
Within this widget is also configured other searches but on other text type fields.
My intention is that I only filter the PROPIEDAD_ID field.


Thanks for your help

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Alberto,

   Pass more than one value using a comma in the url (i.e. /webappbuilder/?id=27&PROPIEDAD_ID=50,100)

I have now made sure that if you have only on query setup it does not care about the name of the query.

You will be responsible for your requirement of querying everything if there is not a PROPIEDAD_ID in the url (I can't do everything for your ).

Here is how to setup the query for a number field and a list of comma separated values.

Here are the code changes to the Widget.js

_initSelf changes (lines 58 - 61).

      _initSelf:function(){
        var queries = this.config.queries;

        if(queries.length === 0){
          html.setStyle(this.tasksNode, 'display', 'none');
          html.setStyle(this.noQueryTipSection, 'display', 'block');
          return;
        } 

        //create query tasks
        array.forEach(queries, lang.hitch(this, function(singleConfig, index){
          var defaultIcon = this.folderUrl + "css/images/default_task_icon.png";
          queryUtils.dynamicUpdateConfigIcon(singleConfig, defaultIcon);
          var name = singleConfig.name;
          var strTr = '<tr class="single-task">' +
            '<td class="first-td"><span class="task-icon"></span></td>' +
            '<td class="second-td">' +
              '<div class="list-item-name task-name-div"></div>' +
            '</td>' +
          '</tr>';
          var tr = html.toDom(strTr);
          var queryNameDiv = query(".task-name-div", tr)[0];
          queryNameDiv.innerHTML = name;
          html.place(tr, this.tasksTbody);

          var iconNode = query("span.task-icon", tr)[0];
          var icon = singleConfig.icon;

          if (icon) {
            var size = 16;
            var symbolNodeStyle = null;
            var isImgType = icon.url || icon.imageData;

            if (isImgType) {
              icon.setWidth(size);
              icon.setHeight(size);
            } else {
              symbolNodeStyle = {
                width: size + 1,
                height: size + 1
              };
              icon.setSize(size);
            }

            var symbolNode = jimuSymUtils.createSymbolNode(icon, symbolNodeStyle);
            html.place(symbolNode, iconNode);
          }

          tr.taskIndex = index;
          tr.singleConfig = singleConfig;
          if(index % 2 === 0){
            html.addClass(tr, 'even');
          }else{
            html.addClass(tr, 'odd');
          }
        }));

        var params = this.mapManager.urlParams;
        if(params.PROPIEDAD_ID){
          queries[0].filter.parts[0].valueObj.value =  params.PROPIEDAD_ID.split(',');
        }
      },

_onClickTaskTr changes (lines 53 - 56).

      _onClickTaskTr: function(tr){
        //this._getLayerInfoAndServiceInfo(tr).then(lang.hitch(this, function(response){
        this._getLayerInfoAndRelationshipLayerInfos(tr).then(lang.hitch(this, function(response){
          var layerInfo = response.layerInfo;
          var layerObject = response.layerObject;
          //var serviceInfo = response.serviceInfo;
          var relationshipLayerInfos = response.relationshipLayerInfos;
          var relationshipPopupTemplates = response.relationshipPopupTemplates;
          tr.singleConfig.objectIdField = jimuUtils.getObjectIdField(layerInfo);
          var popupInfo = this._getPopupInfo(layerInfo, tr.singleConfig);
          if(!popupInfo){
            console.error("can't get popupInfo");
          }
          popupInfo.fieldInfos = queryUtils.getPortalFieldInfosWithoutShape(layerInfo, popupInfo.fieldInfos);
          delete popupInfo.readFromWebMap;
          //now we get all layerDefinitions and popupInfos
          //we prepare currentAttrs here
          var currentAttrs = SingleQueryLoader.getCleanCurrentAttrsTemplate();
          currentAttrs.queryTr = tr;
          currentAttrs.config = lang.clone(tr.singleConfig);
          currentAttrs.config.popupInfo = popupInfo; //add popupInfo attribute
          currentAttrs.layerInfo = layerInfo;
          currentAttrs.layerObject = layerObject;
          //currentAttrs.serviceInfo = serviceInfo;
          currentAttrs.relationshipLayerInfos = relationshipLayerInfos;
          currentAttrs.relationshipPopupTemplates = relationshipPopupTemplates;
          currentAttrs.query.maxRecordCount = layerInfo.maxRecordCount || 1000;

          currentAttrs.queryType = queryUtils.getQueryType(layerInfo);

          //after get currentAttrs, we can show task setting pane destroy the old TaskSetting dijit and create a new one
          if (this.currentTaskSetting) {
            this.currentTaskSetting.destroy();
          }
          this.currentTaskSetting = null;
          this._showTaskSettingPane();
          this.currentTaskSetting = new TaskSetting({
            nls: this.nls,
            map: this.map,
            showFilterLabel:this._showFilterLabel,
            criteiraLabel:this.config.criteiraLabel,
            spatialFilterLabel:this.config.spatialFilterLabel,
            currentAttrs: currentAttrs,
            layerInfosObj: this.layerInfosObj,
            onBack: lang.hitch(this, function() {
              this._showTaskListPane();
            }),
            onApply: lang.hitch(this, function(currentAttrs) {
              this._onBtnApplyClicked(currentAttrs);
            })
          });

          var params = this.mapManager.urlParams;
          if(params.PROPIEDAD_ID){
            this.currentTaskSetting._onBtnApplyClicked();
          }

          if (this.currentTaskSetting.canAutoRunning()) {
            this._switchToResultTab();
            //if the task can run without specify other parameters, then we run it automatically
            this.currentTaskSetting.run();
          }

          this.currentTaskSetting.placeAt(this.taskSettingContainer);
        }), lang.hitch(this, function(err){
          console.error("can't get layerInfo", err);
        }));
      },
0 Kudos
AlbertoCañivano
New Contributor III

Thanks for your help, Robert. It works perfect! I will finish the query for only quering by PROPIEDAD_ID field.

0 Kudos