ttmt
ttmt

Reputation: 4984

D3 Angular - line break in axis label

I have a stackblitz here - https://stackblitz.com/edit/lable-line-break-p1f9hb?file=src/app/bar-chart.ts

The x-axis have long labels that I need to split after the second word, so I have a title and sub title

When I'm creating the x-axis I'm calling a function that splits the string up and adds them as separate tspans

this.chart.append("g")
    .call(this.x_axis)
    .classed('x-axis', true)
    .attr("transform", "translate(0," + this.height + ")")

    .selectAll(".tick text")
    .each(this.insertLinebreak)


private insertLinebreak (d) {

    let labels = d3.select(".x-axis .tick text");
    let words = d;
    labels.text('');

    let index = words.indexOf(' ', words.indexOf( ' ' ) + 1)
    let title = words.substr(0, index)
    let subtitle = words.substr(index + 1)

    let tspantitle = labels.append('tspan').text(title)
    let tspansubtitle = labels.append('tspan').text(subtitle)

    tspantitle
      .attr('x', 0)
      .attr('dy', '15')
      .attr('class', 'x-axis-title');
    tspansubtitle
      .attr('x', 0)
      .attr('dy', '16')
      .attr('class', 'x-axis-subtitle');

};  

My probelm is its adding them in the wrong order and missing one of the titles

What I am doing wrong, is there a better way to do this.

Upvotes: 2

Views: 864

Answers (1)

Martin Parenteau
Martin Parenteau

Reputation: 73731

The first line in insertLinebreak is the source of the problem, because it retrieves all the label elements every time you want to process one of them (watch the console in this stackblitz):

private insertLinebreak(d) {
  let labels = d3.select(".x-axis .tick text"); // <-- This line causes the problem
  ... 
}

In order to select only the label that you are processing, use d3.select(this):

private insertLinebreak(d) {
  let labels = d3.select(this);
  ... 
}

See this stackblitz for a demo.

Upvotes: 1

Related Questions