Saqib Ali
Saqib Ali

Reputation: 12585

How to change d3.js text entry from within that text's onclick method?

My AngularJS app uses d3.js to draw a nice chart.

While drawing this chart, it uses paints some text on the screen. I want to change that text when someone clicks on it based on the boolean value of myCondition. This is how I do it:

          var nodeEnter = node.enter()

          var myLabel = nodeEnter.append("text")
              .attr("x", 50)
              .attr("dy", "3")
              .text("Hello World")
              .style("fill-opacity", 0)
              .style("cursor", "pointer")
              .on("click", function(d) {
                  if (myCondition) 
                      myLabel.text("Mars");
                  else
                      myLabel.text("Venus");
                }
              );

It sorta works. The value of the text does indeed change from Hello World to Mars or Venus. But there is a problem. This code is called within a recursive function and within a loop. That recursion + loop use the same code to draw numerous such texts on the SVG Container. So when I click this label, not only does it change the text that I want. It also changes the text in other places too! I don't want that. How can I prevent it?

I really just need a way I can address this or myself from within the click function so it knows I'm talking about the object. How?

Upvotes: 1

Views: 1501

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

Without knowing your recursive function and the loop, I'll try two different approaches, I hope that one of them works.

The first one is using this for the click event:

var myLabel = nodeEnter.append("text")
          .attr("x", 50)
          .attr("dy", "3")
          .text("Hello World")
          .style("fill-opacity", 0)
          .style("cursor", "pointer")
          .on("click", function(d) {
              if (myCondition) 
                  d3.select(this).text("Mars");
              else
                  d3.select(this).text("Venus");
            }
          );

If this doesn't work, you can try to set a specific class to your different myLabel texts. Doing this, even if you have several myLabel in your SVG, each one has a unique class. Suppose that index is a specific value for the loop (like i). So, you can try:

var myLabel = nodeEnter.append("text")
          .attr("x", 50)
          .attr("dy", "3")
          .attr("class", "myLabel" + index)//index is any value unique for the loop
          .text("Hello World")
          .style("fill-opacity", 0)
          .style("cursor", "pointer")
          .on("click", function(d) {
              if (myCondition) 
                  d3.selectAll(".myLabel" + index).text("Mars");
              else
                  d3.selectAll(".myLabel" + index).text("Venus");
            }
          );

Upvotes: 5

Related Questions