1

I want dynamically create a set of buttons generated by a list of strings:

keys = [ "Temp_Innen", "Temp_Außen", "Druck", "Feuchte_Innen", "Feuchte_Außen", "PH10", "PH25" ]

Those strings shall also be used in each button on the onClick event function(parameter)...

I use this to create the buttons inside the body:

d3.select('body')
  .selectAll('button')
  .data(keys)
  .enter()
  .append('button')
  .text(d => d)
  .attr('type', 'button');

Which gives me nice buttons: enter image description here

But how can I add dynamically add each string into an function parameter that is called via onClick? I tried this but it doesnt work:

.attr('onClick',`clicked(${d => d})`);

But that does not write the strings into the clicked() parameter, instead its written unexpressed as text:

<button type="button" onClick="clicked(d => d)">Temp_Innen</button>
<button type="button" onClick="clicked(d => d)">Temp_Außen</button>
...

Is there a way to do that dynamically or should I consider writing all those buttons static in my html file?

Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
Paul G.
  • 461
  • 6
  • 21

3 Answers3

3

First of all, unlike the code in your question your answer works because the first argument passed to the anonymous function inside the attr method is the datum bound to the element, as described everywhere in the API:

[...] if the value is a function, it is evaluated for each selected element, in order, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (nodes[i])

On the other hand, in your question, this...

`clicked(${d => d})`

...is simply a string, and d is never evaluated.

That being said, let's proceed to the answer: a lot of people advise against using inline events, or DOM onevent handlers, such as the onClick in your question. I'll not get into that discussion (see here); however, I'd say that adding an event listener with D3 on method is the idiomatic way.

That is as simple as:

.on("click", d => {
    //code here
})

Here is the demo:

const keys = ["Temp_Innen", "Temp_Außen", "Druck", "Feuchte_Innen", "Feuchte_Außen", "PH10", "PH25"];

d3.select('body')
  .selectAll('button')
  .data(keys)
  .enter()
  .append('button')
  .text(d => d)
  .attr('type', 'button')
  .on("click", d => console.log("you clicked " + d));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
0

That works so far:

.attr('onClick',(d) => {
  return `clicked("${d}")`});

is correctly expressed as:

<button type="button" onclick="clicked('Temp_Außen')">Temp_Außen</button>
<button type="button" onclick="clicked('Temp_Innen')">Temp_Innen</button>
Paul G.
  • 461
  • 6
  • 21
0
d3.select('body')
  .selectAll('button')
  .data(keys)
  .enter()
  .append('button')
  .text(d => d)
  .attr('type', 'button')
  .attr('onClick', addClickFunction);

define your function addClickFunction(d, i) where your values are in d and i

  • Always wondering where the 'd' parameter comes from in d3.js code... I know it represents a row from my data but where comes 'd' into scope? Is it introduced by the .data(keys)? – Paul G. Aug 21 '20 at 07:49
  • I think d and i represents the array like i for index and d for key. I guess so yes – Niklas Schäffer Aug 21 '20 at 07:50