0

I have created a test app to replicate the issue I am experiencing.

codebase: https://github.com/mohammadfarooqi/event-drops-d3-test-app sample demo deployed (view in safari to see the issue): https://mohammadfarooqi.github.io/event-drops-d3-test-app/

I am using event-drops timeline to display some 'drops' (points on timeline). I have created the timeline in a component called 'comp-a'. I have also created a component called 'comp-b' that uses 'comp-a'. I also have a button in comp-b that routes the user to 'comp-a'.

The issue that I am having is that, in comp-b the event-drops timeline displays with no issues including the 'drops' (points on timeline). However, when we click on the button to go to 'comp-a' from 'comp-b', the comp-a component renders however, the 'drops' on the timeline do not show in Safari (mobile/tablet) however all works in Chrome.

comp-a.component.html

<div id="eventdrops-demo"></div>

comp-a.component.ts

import { Component, OnInit } from '@angular/core';
import * as d3 from 'd3v4';
import eventDrops from 'event-drops';

@Component({
  selector: 'app-comp-a',
  templateUrl: './comp-a.component.html',
  styleUrls: ['./comp-a.component.css']
})
export class CompAComponent implements OnInit {

  constructor() { }

  ngOnInit() {
    const chart = eventDrops({
      d3,
      drop: {
        date: d => d.date
      }
    });

    const repositoriesData = [
      {
        name: 'admin-on-rest',
        data: [{ date: new Date('2018/01/15 14:21:31') } ],
      },
      {
        name: 'event-drops',
        data: [{ date: new Date('2018/01/15 13:24:57') } ],
      },
      {
        name: 'sedy',
        data: [{ date: new Date('2018/01/15 13:25:12') } ],
      },
    ];

    d3
      .select('#eventdrops-demo')
      .data([repositoriesData])
      .call(chart);
  }

}

comp-b.component.html

<p>
  comp-b works!
</p>

<app-comp-a></app-comp-a>

<button (click)="goto()">test</button>

comp-b.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
@Component({
  selector: 'app-comp-b',
  templateUrl: './comp-b.component.html',
  styleUrls: ['./comp-b.component.css']
})
export class CompBComponent implements OnInit {

  constructor(private router: Router) { }

  ngOnInit() {
  }

  goto() {
    this.router.navigate(['a']);
  }

}

app-routing.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';

import { CompAComponent } from './components/comp-a/comp-a.component';
import { CompBComponent } from './components/comp-b/comp-b.component';

const routes: Routes = [
  { path: '', component: CompBComponent },
  { path: 'a', component: CompAComponent }
];

@NgModule({
  imports: [
    CommonModule,
    RouterModule.forRoot(routes)
  ],
  exports: [ RouterModule ],
  declarations: []
})
export class AppRoutingModule { }

1 Answers1

0

Just for future reference for someone else running into this issue. Basically as mentioned the 'dots' were not being shown in safari. The reason for that was that in SPA the paths are generated on the fly (virtual paths). The event-drops lib add's a css style called 'filter': 'url(#metaballs)', and safari did not understand that the path to #metaballs in the svg is actually domain/virtual/route/#metaballs. Therefore the fix was to grab the returned d3 object as shown in comp-a.component.ts and simply over write the filter property for all g.drops with filter should be 'url(' + window.location.href + '#metaballs)'.

ie: d3.select('#eventdrops-demo').selectAll('g.drops').style('filter', 'url(' + window.location.href + '#metaballs)')

Hope this helps.