D3.js и Ionic 2: элементы не в DOM при просмотре второй страницы

Я создал простое приложение Ionic для тестирования интеграции d3.js. Его можно найти здесь: https://github.com/wberger/ionic2-d3js-test

Я сделал интеграцию следующим образом:

  1. Создайте приложение с боковой навигацией и одной страницей (home.html)
  2. Добавьте home.html в меню.
  3. Загрузите d3.js в index.html: <script src="https://d3js.org/d3.v4.min.js"></script>
  4. Добавьте <div id="chart"></div> к home.html
  5. Создайте диаграмму в ngAfterViewInit() в home.ts

Шаблон home определяется следующим образом (источник ):

<ion-header>
  <ion-navbar>
    <button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  The world is your oyster.
  <p>
    If you get lost, the <a href="http://ionicframework.com/docs/v2">docs</a> will be your guide.
  </p>
  <div id="chart"></div>
  <p>After</p>
</ion-content>

Создание диаграммы реализовано следующим образом (источник ):

  ngAfterViewInit() {
    this.createChart();
  }

  createChart() {
    var chart = d3.select("#chart").append("svg")
      .attr("width", 100)
      .attr("height", 100)
      .append("g");

    var rows = [
      {x: 1, y: 1},
      {x: 2, y: 2},
      {x: 3, y: 3},
    ];

    var xScale = d3.scaleLinear()
            .range([0, 100])
            .domain([1, 3]);
    var yScale = d3.scaleLinear()
            .range([100, 0])
            .domain([1, 3]);

    chart.selectAll(".dot")
      .data(rows)
      .enter().append("circle")
      .attr("class", "dot")
      .attr("cx", (row) => { return xScale(row.x) })
      .attr("cy", (row) => { return yScale(row.y) })
      .attr("r", 3.5);
  }

При запуске приложения диаграмма отображается так, как задумано. Но при (повторном) открытии страницы из бокового меню графика нет. При проверке TS/DOM в Google Chrome я могу наблюдать следующее поведение при повторном открытии:

  • ngAfterViewInit() вызывается и, в свою очередь, вызывает 'createChart()'
  • Ранее созданные элементы SVG все еще там
  • Второй элемент SVG создается и заполняется createChart()

После ngAfterViewInit() созданный SVG исчезнет. Кажется, что DOM заменен пустым (или кэшированным??) шаблоном.

Итак, мои вопросы:

  • Что здесь не так? Что я должен знать?
  • Как я могу это исправить?

person thewulf    schedule 08.08.2016    source источник
comment
Здравствуйте, thewulf, у вас была возможность решить эту проблему и заставить d3js работать в Ionic 2? Спасибо за ваш отзыв! Антуан.   -  person Antoine Beloeuvre    schedule 30.11.2016


Ответы (1)


Я решил проблему, построив диаграмму как компонент:

@Component({
  selector: 'my-chart',
  inputs: ['options', 'data'],
  template: ``
})
export class MyChart implements OnChanges {

  el: any;
  options: MyChartOptions;
  data: MyChartData;

  chart: any;
  arcMap: any;

  /**
   * Initializes the component with the root element.
   */
  constructor(@Inject(ElementRef) elementRef: ElementRef) {
    this.el = elementRef.nativeElement;
  }

  /**
   * Handler for binding changes.
   * @param changes The changed bound values.
   */
  ngOnChanges(changes) {
    if (changes.options) {
      this.updateWithOptions(this.options);
    }

    if (changes.data) {
      this.updateWithData(this.data);
    }
  }

  // handlers, drawing etc. ...
}

Затем его можно интегрировать следующим образом:

<my-chart [data]="chartData" [options]="chartOptions"></my-chart>

Не забудьте зарегистрировать компонент в app.module.ts, например:

import { MyChart } from '../components/charts/my-chart';

// ...

@NgModule({
  declarations: [
    // ...
    MyChart
  ],
  imports: [
    // ...
  ],
  bootstrap: [MyApp],
  entryComponents: [
    // ...
  ],
  providers: [
    // ...
  ]
})
person thewulf    schedule 27.02.2017