0
votes

I have several Angular components that I would like to layout on the same webpage, so I am using Angular mat-grid-list and mat-grid-tiles to do this. However, I am running into a size problem. One of the components is a time series plot with a legend and whenever it renders in the mat-grid-tile, it overfills the box, and in another bar plot, the box is underfilled. Here is some example code:

time-series-component.ts

import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import * as d3 from 'd3';
import { ScaleOrdinal } from 'd3';

@Component({
  selector: 'time-series-component',
  templateUrl: './time-series-component.html',
  styleUrls: ['./time-series-component.component.scss'],
})
export class TimeSeriesComponent implements OnInit {
  private width = 1000;
  private height = 620;

  private svg: d3.Selection<SVGGElement, unknown, HTMLElement, any>;
  private xAxis: d3.ScaleTime<number, number>;
  private yAxis: d3.ScaleLinear<number, number>;

  ngOnInit(): void {
    this.createGroups();
    this.createLinePlot();
  }

  createGroups(): void {
    this.groupedData = d3.group(
      this.timeSeriesData,
      (d: TimeSeriesDatum) => d.id,
    );
  }

  createLinePlot(): void {
    this.createSVG();
    this.createAxes();
    this.addData();
    this.addClickableLegend();
  }

  createSVG(): void {
    this.svg = d3
      .select('#time-series-component')
      .append<SVGGElement>('svg')
      .classed('svg-content', true)
      .attr('viewBox', `0 0 ${this.width} ${this.height}`)
      .attr('preserveAspectRatio', 'xMidYMid meet')
      .append('g');
  }

  createAxes(): void {
    this.createX();
    this.createY();
    this.attachAxes();
    this.addAxisLabels();
  }

  createX(): void {
    this.xAxis = d3
      .scaleTime()
      .domain(
        d3.extent(this.timeSeriesData, (d: TimeSeriesDatum) =>
          this.parseDate(d.date),
        ),
      )
      .range([0, this.width]);
  }

  createY(): void {
    this.yAxis = d3
      .scaleLinear()
      .domain([
        0,
        d3.max(
          this.timeSeriesData,
          (d: TimeSeriesDatum) => d.yvalue,
        ),
      ])
      .range([this.height, 0]);
  }

  attachAxes(): void {
    this.svg
      .append('g')
      .attr('transform', `translate(30, ${this.height})`)
      .call(d3.axisBottom(this.xAxis))
      .style('font-size', '10px');
    this.svg.append('g').call(d3.axisLeft(this.yAxis));
  }

There is more, but this is the important stuff. I have 2 more of these components and I am putting them in a mat-grid-list for layout (first component spans two columns, and the next two are one row below the first and span 1 column each). The parent-component.ts simply gathers the data and then passes it to the components through the html.

parent.html

<div
  class="container"
  id="nlp-modeling"
  fxFlexFill
  fxLayout="column">

  <h1>Modeling
    <mat-icon class="info-icon" aria-hidden="false"
      matTooltip=
        "This analytic blah blah blah"
        matTooltipPosition="below">help_outline
      </mat-icon>
  </h1>

  <mat-grid-list cols="2">

    <mat-grid-tile
      [colspan]="2">

      <div class="container">
     
        <mat-grid-tile-header>
            <h2>Time Series</h2>
        </mat-grid-tile-header>

        <time-series-component
          *ngIf="timeSeriesData"
          [timeSeriesData]="timeSeriesData">
        </time-series-component>
  
      </div>

    </mat-grid-tile>

    <mat-grid-tile
      [colspan]="1">
      <div class="container">

        <mat-grid-tile-header>
          <h3>First Bar Chart</h3>
        </mat-grid-tile-header>

        <bar-chart-one
          *ngIf="barChartData1"
          [barChartData1]="barChartData1">
        </bar-chart-one>

      </div>

    </mat-grid-tile>

    <mat-grid-tile
      [colspan]="1">

      <div class="container">

        <mat-grid-tile-header>
          <h3>Second Bar Chart</h3>
        </mat-grid-tile-header>

        <bar-chart-two
          *ngIf="barChartData2"
          [barChartData2]="barChartData2">
        </bar-chart-two>

      </div>

    </mat-grid-tile>

  </mat-grid-list>

</div>

I'm just not sure how to ensure that the content stays inside each of the mat-grid-tiles. In some cases, the plot extends beyond the width of the cell, the x- and/or y-axis is cut off. Each of the component html files are of the same structure: <div id="time-series-component" class="svg-container"></div>. I'm a little lost on how to embed these components in the Angular mat-grid-list/mat-grid-tile structure.

1
Could you create a stackblitz example? - StepUp
Yea, I probably can. It might take a little bit. - CopyOfA

1 Answers

0
votes

One of solutions would be just to create a class which prevents overflow. So try to set max-height and max-width:

.foo {
    max-height: inherit;
    max-width: inherit:
}

and apply it:

<mat-grid-tile
      [colspan]="1">
      <div class="container foo">

        <mat-grid-tile-header>
          <h3>First Bar Chart</h3>
        </mat-grid-tile-header>

        <bar-chart-one
          *ngIf="barChartData1"
          [barChartData1]="barChartData1">
        </bar-chart-one>

      </div>

</mat-grid-tile>