Destroy and recreate new filteringselect

3830
6
Jump to solution
06-24-2016 01:23 PM
TracySchloss
Frequent Contributor

I don't have my services at 10.3, so I can't use the search widget las a find to search through my data.  Instead, I'm creating my own version.

I want to have an input field that allows the user to enter in part of a school name.  Based on the string they enter, I want to display a list of elements that include what they entered.  This becomes a filteringselect they can choose from.

This works for the first pass.  My sequence for destroying the previous filteringselect and creating a new one is off.  I thought I could wrap it in a div tag and use domConstruct.empty('searchDivName').  However when I attempt to create a new filteringselect, I'm getting one of those 'Tried to register widget with id XXX, but this is already registered' errors. 

I thought if I just emptied the div that contained the original filteringselect, I'd be OK.  Maybe I'm trying to destroy the wrong element?

<div id="toolDiv">
<label for="txtSchool > School Search </label>
       <input id="txtSchool" type="text" placeHolder='Enter school' />
          <div id="schoolSearchDiv" >  </div>
  <div id="schoolNote" class="tip" ></div>
 </div>

event listener

  on(dom.byId("txtSchool"), "keydown", function(evt){
    switch (evt.keyCode){
        case keys.ENTER:
  var tbVal = evt.target.value
      console.log("You entered: " + tbVal );
   mySchoolSelect.createSelect(tbVal,app.pointLayer);
      break;
      default:
    }
  });

mySchoolSelect.js that executes

define ([  
    "dojo/on",
    "dojo/dom",
  "dojo/dom-construct",
  "dojo/dom-class",
  "dojo/_base/array",
    "dijit/registry", 
    "dojo/store/Memory",
    "dijit/form/FilteringSelect",
    "esri/tasks/query",
    "esri/tasks/QueryTask",
    "esri/tasks/FindParameters",
    "esri/tasks/FindTask"
    ], function (  
      on,dom,domConstruct, domClass, arrayUtils, registry,Memory,FilteringSelect,Query,QueryTask,
   FindParameters,FindTask
    ) {  
    return {
      createSelect: function(tbVal,pointLayer){
       domConstruct.empty('schoolSearchDiv');
        var selectList = [];
        var urlPath = pointLayer.url;  //creates the proper url for findtask from a featurelayer url
        var urlLen = urlPath.length;
        var lastPos = urlPath.lastIndexOf("/");
        var findUrl = urlPath.substr(0, lastPos);
        
          var findTask = new FindTask(findUrl);
          findParams = new FindParameters();
          findParams.returnGeometry = false;
          findParams.layerIds = [0];  
          findParams.searchFields = ['Facility']; //Fields are CASE SENSITIVE
          findParams.outSpatialReference = app.spatialReference;   
          findParams.searchText = tbVal;


  findTask.execute(findParams).then(function(results){
  if (results.length < 1) {
    alert("No matches found for " + tbVal);
  dom.byId("schoolNote").innerHTML = "No matches found";
  }else {
  console.log("You found " + results.length + " matches");  
  dom.byId("schoolNote").innerHTML = results.length + " matches found, please select one";

  domConstruct.create("input", {id: 'schoolSelDiv' }, "schoolSearchDiv" );
  selectList.length = 0;

  arrayUtils.forEach(results, function(r){
  var name = r.feature.attributes.Facility + " - " + r.feature.attributes.City;
  var val = r.feature.attributes.CtyDist;
  selectList.push({
  label: name,
  value: val
  });
  })
  selectList.sort(function(item1, item2){
  var label1 = item1.label.toLowerCase(), label2 = item2.label.toLowerCase();
  return (label1 > label2) ? 1 : (label1 < label2) ? -1 : 0;
  });

  var dataStore = new Memory({
  data: selectList,
  idProperty: "value"
  });

  var mySelect = new FilteringSelect({
  id: 'schoolSelect',
  placeHolder: 'Pick one',
  ignoreCase: true,
  queryExpr: '${0}*',
  maxHeight: 200,
  store: dataStore,
  searchAttr: 'label'
  }, "schoolSelDiv");

  mySelect.startup();


  on(mySelect, 'change', function(){
  var selectedCode = mySelect.value;
  console.log("mySelectchange event, selected value: " + selectedCode);
  dom.byId("schoolNote").innerHTML = "";
  });
  }        
        });
        function errorHandler(err){
          console.log("error on populate Dropdown, queryTask, error: " + err.details);
        }   
     }
  }
});
0 Kudos
1 Solution

Accepted Solutions
TracySchloss
Frequent Contributor

In the end I separated the creation and populating of the filtering select, so I only created it one time, and after that just populated it. 

 

// search for school by name, used to identify district

   on(dom.byId("txtSchool"), "keydown", function(evt){

  if (!app.mySelect) {  //creates a new empty filteringselect, assuming 1st time usage of this option

  mySchoolSelect.initSelect();

  }

    switch (evt.keyCode){

        case keys.ENTER:

  var tbVal = evt.target.value

//searches schoollayer for name containing string, populates filteringselect with only those that match

   mySchoolSelect.populateSelect(tbVal,app.schoolLayer);

      break;

      default:

    }

  });

View solution in original post

6 Replies
RobertScheitlin__GISP
MVP Emeritus

Tracy,

  When I have to create, destory, and re-create a dijit I always wrap it in a holder div and then use domConstruct.empty on that holder div and add back the re-created dijit to the holder div.

0 Kudos
TracySchloss
Frequent Contributor

That's what I think I'm doing with

domConstruct.empty('schoolSearchDiv');

I'm confused on whether or not I need to create a plain dom 'input' to use before I create my filteringSelect.  

domConstruct.create("input", {id: 'schoolSelDiv' }, "schoolSearchDiv" );

var mySelect = new FilteringSelect({

id:'schoolSelect',

placeHolder: 'Pick one',

ignoreCase: true,

queryExpr: '${0}*',

maxHeight: 200,

store: dataStore,

searchAttr: 'label'

}, "schoolSelDiv");

I hope to catch some error on what I'm calling the new dom elements I'm creating and which I'm telling it to destroy/empty.   I am seeing the original filteringselect get removed during domConstruct.empty.  It seems to be creating a new empty input DOM element, prior to the new FilteringSelect, but then I'm getting the widget register ID error. 

Here's a link: Find District by School

JohnGrayson
Esri Regular Contributor

One way to avoid the error is by not assigning an id, that way a new unique id is generated each time; this works ok as long as you don't need to know the id of the FilteringSelect, as for example when trying to find it via registry.byId(...).  However, a better solution is to create the FilteringSelect once and then just set the store property whenever you create a new store.

RobertKirkwood
Occasional Contributor III

john,

How do i go about setting the property of the store? I am trying to refresh the store after the user saves a new record. I am creating the filtering select only once. However, when I save the data to the data base i am having difficulty refreshing the store in the filtering select even when i rerun the query

0 Kudos
RobertKirkwood
Occasional Contributor III

John,

I found it! 

dijit.byId('myFilteringSelect').set("store", myStore)

0 Kudos
TracySchloss
Frequent Contributor

In the end I separated the creation and populating of the filtering select, so I only created it one time, and after that just populated it. 

 

// search for school by name, used to identify district

   on(dom.byId("txtSchool"), "keydown", function(evt){

  if (!app.mySelect) {  //creates a new empty filteringselect, assuming 1st time usage of this option

  mySchoolSelect.initSelect();

  }

    switch (evt.keyCode){

        case keys.ENTER:

  var tbVal = evt.target.value

//searches schoollayer for name containing string, populates filteringselect with only those that match

   mySchoolSelect.populateSelect(tbVal,app.schoolLayer);

      break;

      default:

    }

  });