Nzall
Nzall

Reputation: 3555

What is the correct way to set a div as the dropdown for a Dojo widget?

I asked a related question about this recently: Dojo _hasDropDown - How do I declaratively bind the properties?. However, I've been struggling with this problem for about 30 hours by now (20 of those before the last question), and I don't feel like I'm any closer. I'd normally edit the old question, but it would change the scope too much and invalidate existing answers.

My problem:

I have the following combobox and Memory store combined with a Struts2 request-scope servlet as part of machineOverview.jsp:

<div data-dojo-type="dojo/store/Memory"                                                  
    data-dojo-id="machineNameStore"                                                      
    data-dojo-props="<s:property value='%{getNameJsonString()}'/>"></div>                
<s:set name="MachineName" value="machineSearchView.name"                                 
    scope="request"></s:set>                                                             
<div data-dojo-type="dijit/form/ComboBox"                                                
    data-dojo-props="store:machineNameStore, searchAttr:'name', value:'${MachineName}'"  
    name="machineSearchView.name" id="machineSearchView.name"></div>

I have this custom Dojo Widget in js/widgets/templates/ExpandableSearchComponent.html:

<div class="${baseClass}">
    <div data-dojo-type="dijit/form/TextBox"
    name="${SearchViewFieldName}TextBox"
    class="${baseClass}TextBox"
    data-dojo-props="placeholder:'${fieldName}'"></div>
    <div class="${baseClass}Container" data-dojo-attach-point="containerNode"></div>
</div>

With this Javascript behind it in js/widgets/ExpandableSearchComponent.js:

/**
 * Javascript for ExpandableSearchComponent
 */
define([ "dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin",
        "dojo/text!./templates/ExpandableSearchComponent.html"], 
          function(declare, _WidgetBase, _TemplatedMixin, template) {

    return declare("js/widgets/ExpandableSearchComponent", [ _WidgetBase,
            _TemplatedMixin ], {
        templateString : template,
        SearchViewFieldName : "",
        fieldName : ""          
    });

});

What I'm trying to do is essentially replace the first snippet with the below:

<div data-dojo-type="js/widgets/ExpandableSearchComponent"                                  
    data-dojo-props="SearchViewFieldName: 'machineSearchView.name', fieldName: 'Name:'">    
    <div data-dojo-type="dojo/store/Memory"                                                 
        data-dojo-id="machineNameStore"                                                     
        data-dojo-props="<s:property value='%{getNameJsonString()}'/>"></div>               
    <s:set name="MachineName" value="machineSearchView.name"                                
        scope="request"></s:set>                                                            
    <div data-dojo-type="dijit/form/ComboBox"                                               
        data-dojo-props="store:machineNameStore, searchAttr:'name', value:'${MachineName}'" 
        name="machineSearchView.name" id="machineSearchView.name"></div>                    
</div>

When this is done, it should just show a dijit/form/TextBox. When I click this Dijit Textbox, a dropdown should appear with in the dropdown the dojo/store/Memory and the dijit/form/ComboBox. Then, once the Combobox has had an option selected, both the Combobox and the dropdown should collapse again and the dijt/form/TextBox should show the value that was entered in the ComboBox, prefixed with the placeholder.

What I've tried:

I've tried a bunch of things:

  1. I've tried binding _hasDropDown declaratively, which doesn't work.
  2. I've tried binding it programmatically, during which I come into numerous problems with figuring out what to put in the define parameters, what to put in the function parameters, what to put in the declare parameters and what functions to return. I keep getting console errors in Chrome that are hard to figure out why they are happening, like my TextBox not being defined properly or my template Mixins not working properly,...
  3. I've tried putting the original comboBox and Memory store into the widget directly, but I abandoned that path after 1 day because it was a fragile and complicated construction and it wasn't really what we wanted in the end either.

What I'm looking for:

I'm not looking for someone to implement this for me. I'm looking for a working example of using either dijit/_HasDropDown or dijit/popup used in a custom widget that includes:

  1. The HTML of the widget;
  2. The javascript code-behind of the widget;
  3. How to use this widget in a page;
  4. If necessary any related javascript for the page itself.

I've checked the Dojo documentation. There is no tutorial for either of the above dijit components. There is an API reference, but that only contains the Javascript, and even then just for how the API works.

The _HasDropDown Mixin API reference has the Javascript for how to add it to a widget, but not the HTML, and it shows how to create such a widget programmatically, but again without HTML code to explain what objects it is binding the widget to. It also uses Widgets, not a div, which I want to use for formatting reasons.

The dijit/popup API reference has the same issues as the _HasDropDown Mixin reference, meaning it shows the Javascript, but not the HTML or how to use it.

both of these API reference documents confuse me and I can't figure out how to implement them. I've also tried Googling, but most hits are for older versions of Dojo, from before the introduction of AMD modules.

As said a couple of times now, I can't figure out how to make these work. The documentation provided by Dojo explains part but not all of it and it's unclear to me how this all works. Can I even even use a widget in this manner? Will I have to write the textbox and the javascript to create the dropdowns directly into the source of my main page?

I'm hoping for a solution that allows me to just surround the element I want to convert with a div that has a data-dojo-type tag, so I have something semi-portable, but if that's not possible, I'll have to confer with my coworkers.


Clarification: I have read the sources for FilteringSelect, _HasDropDown, Select, ComboBox and some other Dojo components, but my big problem right now is that I can't figure out how they wire their dropDown to the right node.

Upvotes: 0

Views: 899

Answers (1)

pgianna
pgianna

Reputation: 725

Since you are looking for examples, have you checked the sources for the dijit widgets that use _HasDropDown? The documentation mentions Select, ComboBox, DropDownButton and DateTextBox. Their sources should give you a good sense for how to use the mixin, especially in conjunction with the reference pages explaining their use with programmatic and declarative examples.

For example the Select widget source: https://github.com/dojo/dijit/blob/1.10.6/form/Select.js and its reference page: http://dojotoolkit.org/reference-guide/1.10/dijit/form/Select.html

To make thing easier I suggest that you first refine the custom widget that must be dropped, programmaticaly place it as a normal widget and style it. It should then be very easy to use it as a drop down following the examples of the dijit widgets that use _HasDropDown.

Upvotes: 0

Related Questions