Need simple example: add tabs to widget

6774
57
Jump to solution
01-19-2018 08:44 AM
JamesCrandall
MVP Frequent Contributor

LaunchPad theme

WABDev 2.5

Custom Widget

I'm looking for the simplest, most straight forward example of adding 2 tabs to a new widget (an absolute vanilla panel).  THIS thread seemed to be close but I'm not seeing the expected result (no CSS example?). 

Looking for the most basic form of HTML, JS and CSS to get this implemented.

TIA

0 Kudos
57 Replies
JamesCrandall
MVP Frequent Contributor

Hi Robert -- yes, it's in both places! 

define(["dojo/_base/declare",
     "dojo/_base/lang",
     "dojo/_base/Color",
     "dojo/_base/array",
     "dojo/dom-construct",
     "dojo/dom-class",
     "dojo/keys",
     "dojo/on",
     "dojo/Deferred",
     "jimu/BaseWidget",
     "dijit/_WidgetsInTemplateMixin", 
        "dijit/layout/TabContainer"

],
     function(declare,
          lang,
          Color,
          array,
          domConstruct,
          domClass,
          keys,
          on,
          Deferred,
          BaseWidget,
          _WidgetsInTemplateMixin,
                TabContainer) {


return declare([BaseWidget,
               _WidgetsInTemplateMixin
          ], {
               // Custom widget code goes here

               baseClass: "jimu-widget-customwidget",
               LoadingIndicator: null,
               currentFeatures: null,
               printOutlineLayer: null,
               printOutlineConnects: [],
               _isPreparedExhibit: false,

               startup: function() {
                    //  summary:
                    //      Called on initial widget load
                    //      This function sets all of our configurable variables to those set in the settings
                    //      page/file.

                    this.tab = new TabContainer({
                         tabs: [{
                           title: this.nls.input,
                           content: this.inputPaneNode
                         }, {
                           title: this.nls.output,
                           content: this.outputPaneNode
                         }],
                         selected: this.nls.input
                      });
                    this.tab.placeAt(this.domNode);
                    this.tab.startup();

                    window.map = this.map;
                    window.widget = this;


0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

 Try this. All I did was change the order of the modules in the define. It is recommended that basewidget and mixins be at the beginning of your array.

define(["dojo/_base/declare",
     "dijit/_WidgetsInTemplateMixin",
     "jimu/BaseWidget",
     "dojo/_base/lang",
     "dojo/_base/Color",
     "dojo/_base/array",
     "dojo/dom-construct",
     "dojo/dom-class",
     "dojo/keys",
     "dojo/on",
     "dojo/Deferred",
     "dijit/layout/TabContainer"
], 
  function(
     declare,
     _WidgetsInTemplateMixin,
     BaseWidget,
     lang,
     Color,
     array,
     domConstruct,
     domClass,
     keys,
     on,
     Deferred,
     TabContainer
) {

  return declare([BaseWidget, _WidgetsInTemplateMixin], {
               // Custom widget code goes here

               baseClass: "jimu-widget-customwidget",
               LoadingIndicator: null,
               currentFeatures: null,
               printOutlineLayer: null,
               printOutlineConnects: [],
               _isPreparedExhibit: false,

               startup: function() {
                    //  summary:
                    //      Called on initial widget load
                    //      This function sets all of our configurable variables to those set in the settings
                    //      page/file.

                    this.tab = new TabContainer({
                         tabs: [{
                           title: this.nls.input,
                           content: this.inputPaneNode
                         }, {
                           title: this.nls.output,
                           content: this.outputPaneNode
                         }],
                         selected: this.nls.input
                      });
                    this.tab.placeAt(this.domNode);
                    this.tab.startup();

                    window.map = this.map;
                    window.widget = this;‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
JamesCrandall
MVP Frequent Contributor

That did something!  At least now I see some kind of tab-thing -- it's not functional and I can't seem to add another tab, but it's definitely different from where I was.

I'm looking at and incorporating the Geoprocessing widget into the css, html and js -- but it's really complex and I don't think this is the best approach to try and implement tabs into a simple vanilla widget.  I'll mark your last answer as correct but I'm still not progressing as I had hoped with this.

Thanks for your assistance!

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

  Personally I would be using "jimu/dijit/TabContainer" not "dijit/layout/TabContainer". Jimu dijits are lighter weight and simpler.

As far as using the GP widget inside your widget that is a pretty daunting task.

JamesCrandall
MVP Frequent Contributor

As far as using the GP widget inside your widget that is a pretty daunting task

Definitely -- I was only attempting to just use it as reference, I need something to go off of to try and implement a tabbed panel

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

  OK, that makes more sense.

0 Kudos
JamesCrandall
MVP Frequent Contributor

I can't even get THIS to fully work.

The entire widget.html needs to be encapsulated inside of a <div> .. </div> for the widget to open without error, but then the <script> section doesn't seem to fire and nothing appears when a tab is clicked.

The code is pretty much exactly as found in the simple example. 

<div>
<div class="tab">
  <button class="tablinks" onclick="openCity(event, 'London')">London</button>
  <button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
  <button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<div id="London" class="tabcontent">
  <h3>London</h3>
  <p>London is the capital city of England.</p>
  <div class="main-div" data-dojo-attach-point='mainDiv'></div>
</div>

<div id="Paris" class="tabcontent">
  <h3>Paris</h3>
  <p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
  <h3>Tokyo</h3>
  <p>Tokyo is the capital of Japan.</p>
</div>

<script>
function openCity(evt, cityName) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName("tabcontent");
    for (i = 0; i < tabcontent.length; i++) {
        tabcontent[i].style.display = "none";
    }
    tablinks = document.getElementsByClassName("tablinks");
    for (i = 0; i < tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(" active", "");
    }
    document.getElementById(cityName).style.display = "block";
    evt.currentTarget.className += " active";
}
</script>
</div>
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

   OK, Do not use a script tag in the Widgets.html. All you code goes in the Widget.js. Next you will not use elements ids in your html or code. The way it is done in widget development is you reference a html element in your widgets template using the data-dojo-attach-point that you assign to html element instead of ids. Then in your code you get that html element using this.xyz (data-dojo-attach-point="xyz").

JamesCrandall
MVP Frequent Contributor

I see.  Will give it a go!

Much appreciated.

0 Kudos
JamesCrandall
MVP Frequent Contributor

Error: Uncaught ReferenceError: openCity is not defined which I guess the botton classes need to be "data-dojo-attach-event"?  But not sure how to pass the arguments to the openCity function in the .js

Widget.html:

<div>
<div class="tab">
  <button class="tablinks" data-dojo-attach-point='tablinksExhibit' onclick="openCity(event, 'London')">London</button>
  <button class="tablinks" data-dojo-attach-point='tablinksExhibit' onclick="openCity(event, 'Paris')">Paris</button>
  <button class="tablinks" data-dojo-attach-point='tablinksExhibit' onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<div id="London" class="tabcontent" data-dojo-attach-point='tabExibit'>
  <h3>London</h3>
  <p>London is the capital city of England.</p>
  <div class="main-div" data-dojo-attach-point='mainDiv'></div>
</div>
<div id="Paris" class="tabcontent" data-dojo-attach-point='tabExibit'>
  <h3>Paris</h3>
  <p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent" data-dojo-attach-point='tabExibit'>
  <h3>Tokyo</h3>
  <p>Tokyo is the capital of Japan.</p>
</div>

</div>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Widget.js (I didn't do anything with cityName yet):

openCity: function(evt, cityName) {
           // Declare all variables
           var i, tabcontent, tablinks;
           // Get all elements with class="tabcontent" and hide them
           //tabcontent = document.getElementsByClassName("tabcontent");
           tabcontent = domClass.add(this.tabExibit, 'tab');
           for (i = 0; i < tabcontent.length; i++) {
               tabcontent[i].style.display = "none";
           }
           // Get all elements with class="tablinks" and remove the class "active"
           //tablinks = document.getElementsByClassName("tablinks");
           tablinks = domClass.add(this.tablinksExibit, 'tab');
           for (i = 0; i < tablinks.length; i++) {
               tablinks[i].className = tablinks[i].className.replace(" active", "");
           }
           // Show the current tab, and add an "active" class to the button that opened the tab
           document.getElementById(cityName).style.display = "block";
           evt.currentTarget.className += " active";
   },‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos