0

Here is the basic scheme of my app:

enter image description here

Inside parent component I have another component which makes svg chart and inserts all nodes via innerHTML:

//chart.component.html
<div #container>
    <svg:svg [innerHTML]="svg"></svg>
</div>

Svg is made with the data provided by the endpoint. I simply glue pieces of strings together and pass whole string via innerHTML. Some of the elements on the chart need to be able to perform some methods (on click). For example yellow buttons will run (click)="getMoreDataAndDisplay()".

//example from chart.component.ts
getMoreDataAndDisplay() {
  this.endpointTwoService.getMoreSpecificData().subscribe(response => {
    this.dataToDisplay = response.json(); //this need to be passed to data.component
    this.displayTheData == true;
  });
}

After clicking on the button, basing on parameters from the first endpoint, will provide more data from another endpoint and show them in data component.

//parent.component.html
<app-chart></app-chart>

<app-data *ngIf="displayTheData==false"></app-data>

Unfortunately, stuff added by innerHTML seems to be not processed and inserting it like beyond figure in the node but doesn't work:

//example from chart.component.ts
drawRelationButton() {
  //draw rectangle button
  let relationButtonBase = '<rect (click)="getMoreDataAndDisplay()" x="20" y="50" rx="2" ry="2" width="10px" height="10px" stroke="#b3b3b3" fill="#ffffff" stroke-width="1"></rect>'
  return relationButtonBase;
}

I've found similar problems here and here, but since I'm quite new to Angular, feel a bit lost. How to get these buttons work in this case?

Thanks for the help in advance.

mpro
  • 14,302
  • 5
  • 28
  • 43
  • Possible duplicate of [Angular 2: functions/methods on click inside dynamic template (dynamic component)](https://stackoverflow.com/questions/41148129/angular-2-functions-methods-on-click-inside-dynamic-template-dynamic-component) – Estus Flask Feb 13 '18 at 13:18
  • Thanks for your suggestion, besides the plunker provided in that question, is not working for me, it seems that this is the slightly different case than mine. It takes some time to check if solution provided there works for me too. – mpro Feb 13 '18 at 14:07
  • This is same case as yours, only with proper approach (dynamic component instead of innerHTML). If you'll have problems with implementing it, consider re-asking the question with your current attempt. – Estus Flask Feb 13 '18 at 14:10
  • @estus [Check this plunker](https://plnkr.co/edit/bkPaHCU12SREYLAWTBUz?p=preview) please. This is how I generate the svg, glue the pieces together and pass it as a string to innerHTML. So the same as in plunker above, it passes string via the variable, or am I doing it wrong? – mpro Feb 13 '18 at 15:17
  • You need to provide dynamic html through ``, and you're already doing it. You won't be able to do this inside (technically, you can, but you will need another for that) – Estus Flask Feb 13 '18 at 15:28
  • @estus does it mean, that every single node I would add to my svg must be separated component? – mpro Feb 13 '18 at 15:31
  • Not necessarily, you can probably end up with a single – Estus Flask Feb 13 '18 at 15:40
  • @estus doesn't work for me or still doing it wrong? Check [this plunker](https://plnkr.co/edit/ytXZzmwH8CoDZYl6hMTL?p=preview) please, could we move to the chat too? – mpro Feb 13 '18 at 15:55
  • I don't use chats because they don't work well for offline talks. I see. That's design problem because it's expected that `testMe()` will exist in the component (MyDynamicComponent). The proper solution is to create a directive that fetch data on click and replace ` (click)="getMoreDataAndDisplay()"` with it. – Estus Flask Feb 13 '18 at 16:14
  • You will need to modify the way data is handled. Currently data is handled by `chart.component`, and that's bad. endpointTwoService should be responsible not only for fetching but for storing existing data. So you could trigger `endpointTwoService.getSpecificData()` in child component/directibe and subscribe to `endpointTwoService.specificData$` observable in parent. – Estus Flask Feb 13 '18 at 16:15
  • @estus [how about this?](https://plnkr.co/edit/ytXZzmwH8CoDZYl6hMTL?p=preview), if this is wrong, kill me but it works! Just moved `testMe()` to `class MyDynamicComponent {}` – mpro Feb 13 '18 at 16:27
  • `MyDynamicComponent` should be a shallow wrapper around template and contain no own logic. This way you hard-code to be used only with particular scenario. And if you have other places where you need this, MyDynamicComponent will end up with a bunch of hacky unrelated methods. I cannot provide full-fledged answer with working example, but I'd suggest to go with the approach I explained above and refactor service to handle data for all components that use it. – Estus Flask Feb 13 '18 at 16:50
  • It works, but that's basically MVC/MVVM design problem. The issue you're having is known as 'fat controller' - you're giving too much control to controller/view-model (component class), while business logic should be handled by a model (data service). Search for 'slim controller, fat model' for more details on the subject. – Estus Flask Feb 13 '18 at 16:53
  • Thank you very much for your time and knowledge. Tomorrow gonna check it on my code and then will try to improve to approach you recommend. – mpro Feb 13 '18 at 20:23
  • Sure. Consider asking a question with current code and plunker if you will have specific problems with implementation. – Estus Flask Feb 13 '18 at 20:28
  • I hope to get through it nice and easy ;) and I'm afraid duplicates here too :D, but in the case I hit the wall, I do for sure! – mpro Feb 13 '18 at 20:30
  • @estus Coming back with quick question. It is not about displaying data.component this time, but reload chart component, which I do by triggering button from the parent. I have 2 versions of the chart, you can choose by switching the button. Until I had 1 version running hardcoded inside the component, there was no problem. But since I changed it to trigger mode I get [this](https://i.stack.imgur.com/gtMGC.jpg). The new chart is generated on the old one. Should I clear cache somehow? [I use the dynamic component approach you've suggested](https://plnkr.co/edit/ytXZzmwH8CoDZYl6hMTL?p=preview) – mpro Feb 21 '18 at 14:09
  • Hi, I'm not sure what's going on here. It may be not that simple It would be better to ask this in new question with real chart (possibly simplified but able to demonstrate the issue). – Estus Flask Feb 21 '18 at 14:19
  • @estus just FYI: it wasn't a problem with the dynamic component but messed up a with scope and variables ;) – mpro Feb 22 '18 at 14:31
  • Glad it resolved that simple. – Estus Flask Feb 22 '18 at 14:31

0 Answers0