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); } } } });
Solved! Go to Solution.
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:
}
});
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.
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
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.
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
John,
I found it!
dijit.byId('myFilteringSelect').set("store", myStore)
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:
}
});