Rahul Desai
Rahul Desai

Reputation: 15501

Change button text programmatically in Dojo

Here is my code so far:

dojoConfig = {parseOnLoad: true};

resetStopwatch();

require(["dojo/query", "dijit/form/ToggleButton", "dijit/form/Button", "dojo/dom", "dojo/dom-attr", "dojo/domReady!"], function(query, ToggleButton, Button, dom, domAttr){
  //query("#resume").style("display", "none");

  var timeUpdate, flag; 
  flag = false;

  new ToggleButton({
    showLabel: true,
    checked: false,
    onChange: function(val) {
      if (val) {
        this.set('label', 'Stop');

        var milliseconds = seconds = minutes = hours = 0;

        if(flag){
          // fetch current time in the stopwatch
          milliseconds = parseInt(domAttr.get("milliseconds", "innerHTML"));
          seconds      = parseInt(domAttr.get("seconds", "innerHTML"));
          minutes      = parseInt(domAttr.get("minutes", "innerHTML"));
          hours        = parseInt(domAttr.get("hours", "innerHTML"));
        }

        var startTime = new Date();
        timeUpdate = setInterval(function(){
          var timeElapsed = new Date().getTime() - startTime.getTime();

          // calculate hours                
          hours = parseInt(timeElapsed/1000/60/60);
          hours = prependZero(hours);
          domAttr.set("hours", "innerHTML", hours + " h ");

          // calculate minutes
          minutes = parseInt(timeElapsed/1000/60);
          if(minutes > 60)
            minutes = minutes % 60;
          minutes = prependZero(minutes);
          domAttr.set("minutes", "innerHTML", minutes + " m ");

          // calculate seconds
          seconds = parseInt(timeElapsed/1000);
          if(seconds > 60)
            seconds = seconds % 60;
          seconds = prependZero(seconds);
          domAttr.set("seconds", "innerHTML", seconds + " s ");

          // calculate milliseconds 
          milliseconds = timeElapsed;
          milliseconds = prependZero(milliseconds);
          if(milliseconds > 1000)
            milliseconds = milliseconds % 1000;
          if(milliseconds < 10)
            milliseconds = "00" + milliseconds.toString();
          else if(milliseconds < 100)
            milliseconds = "0" + milliseconds.toString();                
          domAttr.set("milliseconds", "innerHTML", milliseconds + " milli");

        },25);  // updated time after every 25ms

      } else {
        this.set('label', 'Resume');
        clearInterval(timeUpdate);
      }
    },
    label: "Start"
  }, "start_stop");

  /*var resumeButton = new Button({
        label: "Resume",
        onClick: function(){
            //clearInterval(timeUpdate);
            //resetStopwatch();        
        }
    }, "resume");  */  

  var resetButton = new Button({
    label: "Reset",
    onClick: function(){
      domAttr.set("start", 'label', "Start");
      clearInterval(timeUpdate);
      resetStopwatch();        
    }
  }, "reset");
});

function resetStopwatch(){
  require(["dojo/dom-attr"], function(domAttr){
    domAttr.set("hours",        "innerHTML", "00 h ");
    domAttr.set("minutes",      "innerHTML", "00 m ");
    domAttr.set("seconds",      "innerHTML", "00 s ");
    domAttr.set("milliseconds", "innerHTML", "000 milli");
  });
}

function prependZero(time){
  if(time < 10){
    time = "0" + time.toString();
    return time;
  }
  else
    return time;
}
#stopwatch, #buttons{
  text-align: center;
}

.claro *
{
  outline: none;
}
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dijit/themes/claro/claro.css">

<div id="stopwatch">
  <span id="hours"></span>
  <span id="minutes"></span>
  <span id="seconds"></span>
  <span id="milliseconds"></span>
</div>
<div id="buttons" class="claro">
  <button id="start_stop"></button>
  <!--<button id="resume"></button>-->
  <button id="reset"></button>
</div>

Consider this use-case: click Start > after some time, click Reset - I plan to change the label from Stop to Start back again. So, I did:

domAttr.set("start", 'label', "Start");   // line # 83

But it is throwing an error:

Uncaught TypeError: Cannot call method 'setAttribute' of null 

Not sure what I am doing wrong here. Please help!

Upvotes: 2

Views: 5149

Answers (2)

Dimitri Mestdagh
Dimitri Mestdagh

Reputation: 44685

In Dojo there is a difference between widgets and DOM nodes. Your start button is a widget, so setting the label of that widget using a DOM node will not work. To change the label of the widget, you first need to retrieve the widget instance using the dijit/registry module or by having a reference to your widget (ToggleButton) already.

After that you can use the appropriate setter to change the label of the widget.

In your case the best thing to do is create a local reference to the new ToggleButton, for example:

var startBtn = new ToggleButton({
    /** Your code */
});

And then do the following:

startBtn.set("label", "Start");

As usual, I also updated your JSFiddle.


If you would like to use the dijit/registry module (which isn't necessary now), you can get a reference to your widget using the widget ID (or the DOM ID) by using:

require(["dijit/registry"], function(registry) {
    registry.byId("start_stop").set("label", "Start");
});

However, in this case it isn't useful, because you have an easier way of referencing your widget, but keep it in mind for future references (or if you start using declarative widgets).

Upvotes: 4

PaulR
PaulR

Reputation: 316

As the documentation states, you should pass a domNode into domAttr.set, not a string. So, instead of passing a string, "start", pass in a domNode (by using a data-dojo-attach-point for example).

I think you should replace it with "this.set('label', 'Start');".

This fixes your problem:

var startButton = new ToggleButton({
    showLabel: true,
    checked: false,
    onChange: function(val) {
       // code
    },
    label: "Start"
}, "start_stop");

var resetButton = new Button({
    label: "Reset",
    onClick: function(){
        startButton.set('label', "Start");
        clearInterval(timeUpdate);
        resetStopwatch();        
    }
}, "reset");

});

Notice that i saved the reference to the startButton, so it can be references in the onClick from the resetButton.

Upvotes: 2

Related Questions