To use: set the dropdownColumns = "<field1>,<field2>,etc"
Ex:
<div dojoType="local.form.MultiColumnComboBox" store="myStore" searchAttr="id" dropdownColumns="id,name"></div>
<div dojoType="local.form.MultiColumnFilteringSelect" store="myStore" searchAttr="id" dropdownColumns="id,name"></div>
You can also override the dropdownFunction instead.
If you want to embed html, make sure to change this.labelType="html" in the function or from the html creation of the combo box.
This is based on ComboBox version 1.4.3 It would not hurt to grab the source for ComboBox and check this routine for changes if you are using a different version.
FilteringSelect is derived from ComboBox and the function I have changed is common to both classes so the same thing works for both of these widgets.
A side note regarding filtering select (that has nothing to do with these changes):
*** [problem: Blank field in FilteringSelect randomly or first time even though it should have been filled with correct value] ***
Reason: The first time a store (or at least the dojox.data.QueryReadStore) reads from the backend server, it will use id= instead of the specified label as learned from the prior read, this is because no prior reads have occurred so it doesn't know any different. The upshot is, since FilteringSelect only accepts valid values, a blank field in your filtering select that should have shown data.
Example: searchAttr="state" and the backend returns something like {'identifier'='state', 'label'='state','items'=[...]}
The first time the fields are filled the backend will be called with id=<data> instead of state=<data>
So make sure your backend code recognizes id as being the same as your search key name. In the above example, treat id= the same as state=
ie:
stateList.php?id=MN should return the same as stateList.php?state=MN
You may not need to use this code if you just want the dropdown to display something different than the textbox.
labelAttr overrides the field that is displayed in the drop-down box, whereas labelFunc() controls the display of the textbox (and the dropdown box if labelAttr is not set).
You could set labelAttr="name" searchAttr="id" to have the drop-down display something different than the text-box portion.
The dropdown menu will even automatically size differently.
You could have your php script hand in the id field and the combined field
Such as
foreach ($items as &$item){ //Using the & symbol to make $item a reference instead of a copy, otherwise this would not work. $item["StateCodeAndName"]=$item["StateCode"]." : ".$item["StateName"]; }Note: You have to turn off autoComplete because it doesn't make sense when the dropdown contains different information than the text field.
If you need a separate drop-down label function that is not tied to the labelFunc, then this code is an example of how to do it.
The _getMenuLabelFromItem() function is what needs to be overridden.
In the example below I only slightly modified this function.
I added this.dropdownFunction?this.dropdownFunction(item):
to the original line: var label = this.labelAttr? this.store.getValue(item, this.labelAttr) : this.labelFunc(item, this.store);
AutoComplete may not work correctly because the drop-down menu data may not match the text-box data.
To fix, you will have to override _autoCompleteText: function(text){...}
I have the code from dijit.form.ComboBox version 1.4.3 at the bottom of this page.
dojo.require("dijit.form.ComboBox"); dojo.declare("local.form.MultiColumnComboBox",[dijit.form.ComboBox],{ dropdownColumns: "", dropdownSeparator: "| ", autoComplete: false, dropdownFunction: function(item){ var label=""; this.labelType = "text"; if (this.dropdownColumns && this.dropdownColumns.length>0){ var fields = this.dropdownColumns.split(','); for (var field in fields){ if (label.length==0){ label = this.store.getValue(item, fields[field]); } else { label = label + this.dropdownSeparator + this.store.getValue(item, fields[field]) } } } return label; }, _getMenuLabelFromItem: function(/*Item*/ item){ var label = this.dropdownFunction?this.dropdownFunction(item):(this.labelAttr? this.store.getValue(item, this.labelAttr) : this.labelFunc(item, this.store)); var labelType = this.labelType; // If labelType is not "text" we don't want to screw any markup ot whatever. if(this.highlightMatch != "none" && this.labelType == "text" && this._lastInput){ label = this.doHighlight(label, this._escapeHtml(this._lastInput)); labelType = "html"; } return {html: labelType == "html", label: label}; } }); dojo.require("dijit.form.FilteringSelect"); dojo.declare("local.form.MultiColumnFilteringSelect",[dijit.for.FilteringSelect],{ dropdownColumns: "", dropdownSeparator: "| ", autoComplete: false, dropdownFunction: function(item){ var label=""; this.labelType = "text"; if (this.dropdownColumns && this.dropdownColumns.length>0){ var fields = this.dropdownColumns.split(','); for (var field in fields){ if (label.length==0){ label = this.store.getValue(item, fields[field]); } else { label = label + this.dropdownSeparator + this.store.getValue(item, fields[field]) } } } return label; }, _getMenuLabelFromItem: function(/*Item*/ item){ var label = this.dropdownFunction?this.dropdownFunction(item):(this.labelAttr? this.store.getValue(item, this.labelAttr) : this.labelFunc(item, this.store)); var labelType = this.labelType; // If labelType is not "text" we don't want to screw any markup ot whatever. if(this.highlightMatch != "none" && this.labelType == "text" && this._lastInput){ label = this.doHighlight(label, this._escapeHtml(this._lastInput)); labelType = "html"; } return {html: labelType == "html", label: label}; } });
I am listing version 1.4.3 of the dijit.form.ComboBox._autoCompleteText(text) function here in case you want to override this function and fix autoComplete.
_autoCompleteText: function(/*String*/ text){ // summary: // Fill in the textbox with the first item from the drop down // list, and highlight the characters that were // auto-completed. For example, if user typed "CA" and the // drop down list appeared, the textbox would be changed to // "California" and "ifornia" would be highlighted. var fn = this.focusNode; // IE7: clear selection so next highlight works all the time dijit.selectInputText(fn, fn.value.length); // does text autoComplete the value in the textbox? var caseFilter = this.ignoreCase? 'toLowerCase' : 'substr'; if(text[caseFilter](0).indexOf(this.focusNode.value[caseFilter](0)) == 0){ var cpos = this._getCaretPos(fn); // only try to extend if we added the last character at the end of the input if((cpos+1) > fn.value.length){ // only add to input node as we would overwrite Capitalisation of chars // actually, that is ok fn.value = text;//.substr(cpos); // visually highlight the autocompleted characters dijit.selectInputText(fn, cpos); } }else{ // text does not autoComplete; replace the whole value and highlight fn.value = text; dijit.selectInputText(fn); } },