1

I have an angular app which for all intensive purposes is order pad.

There is an order entry component, which has say two children (for example purposes):

|-order_entry.component.ts // selector <orderentry_line></orderentry_line>
  -name_component.ts // selector <name></name>
  -quanity_component.ts // selector <qty></qty>

Now when my application first fires up, there are no instances of order_entry.component.ts loaded, I have a button that on click should load the first instance of this component (with an index so I can reference it)

So when a new instance of order_entry.component.ts is requested it updates my HTML with a new instance of:

<orderentry_line></orderentry_line>

Which then in turn creates:

<name></name>
<qty></qty>

Which would create something along the lines of:

<!-- index is the component number generated in order -->
<input type=text name="name_entry" (ngModelChange)="storeNameValue($index, $event)">
<input type=text name="qty_required" (ngModelChange)="storeQtyValue($index, $event)">

So 1 would be the index (for the first component loaded), so multiple instances of the order_entry component could work in harmony.

Also, I need to be able to delete certain components if required, so lets say I created 4 instances, I would need to be able to delete/remove one component on user action.

So far I have adapted some code from this tutorial and come up with this plunker which shows creating multiple instances of one component, but I cannot seem to update the index value correctly (I imagine I could use a global stream service to store this value and relay it) but I wasn't sure if this was the correct way to achieve this (based on my use case).

I have looked at this very detailed answer and it is helpful, but it does not extend to quite what I am looking to achieve.

Graham
  • 7,431
  • 18
  • 59
  • 84
crooksey
  • 8,521
  • 6
  • 30
  • 52

1 Answers1

1

Just maintain the components in an array:

export default class DynamicComponent {
  components = [];

  delete(i:number) {
    this.components[i].destroy();
    this.components.splice(i, 1);
  }

  @Input set componentData(...) {
    ...
    this.components.push(component);
  }
<div *ngFor="let c of components, let i=index">
  {{c.instance.c}} - {{c}} 
  <button (click)="delete(i)">delete</button>
</div>

Plunker example

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    Thanks Gunter, that's exactly what I was looking for. – crooksey Feb 23 '17 at 15:12
  • Hi Gunter, how can I call the delete component function from within itself, rough example of what I am trying to achieve: http://plnkr.co/edit/ljUcejh4DsEPUfqRrjxh?p=preview – crooksey Feb 28 '17 at 11:29
  • Would I be best of making DynamicComponent a Service? – crooksey Feb 28 '17 at 11:37
  • I don't see why? What's your reasoning? – Günter Zöchbauer Feb 28 '17 at 12:25
  • Well more of making the components array (a service), so It gives me the ability to call the delete button, inside of each component's template (like my non working plunker example), as opposed to having a separate list of buttons for each component to delete. – crooksey Feb 28 '17 at 12:28
  • I wouldn't pass the index from the component but just look it up when the component is about to be destroyed http://plnkr.co/edit/NFdZJqQ0qWsHVaHtzSA7?p=preview The `showNum` doesn't match the index anymore when a component at the beginning was deleted. – Günter Zöchbauer Feb 28 '17 at 12:31
  • Thanks, I wasn't sure of the "correct Angular way" to do this, one question, the code: "component.instance.dynamic = this;" throws a TS error/warning "Property dynamic does not exist on type '{}'". However the code runs/compiles without error. – crooksey Feb 28 '17 at 12:56
  • I don't use TS myself and Plunker doesn't provide any type feedback, therefore I don't really know. Either you give it the proper type `DynamicComponent` (if I remember correctly) or `any` just to silence the linter. – Günter Zöchbauer Feb 28 '17 at 12:57
  • 1
    Simple fix for now seems to be: "component.instance['dynamic'] = this;" thanks again for the help. – crooksey Mar 01 '17 at 09:14