0

I am trying to create a cart that loads the items dynamically.

Sidebar Component .TS

@ViewChild('cartContainer', { read: ViewContainerRef }) public container;
public componentRef: ComponentRef<any>;

public createComponent(type: any) {
  this.container.clear();
  const factory: ComponentFactory<any> = this.resolver.resolveComponentFactory(CartComponent);
  this.componentRef = this.container.createComponent(factory);
  this.componentRef.instance.type = type;
  this.componentRef.instance.output.subscribe(event => console.log(event));
}

Sidebar Component .HTML

<ng-template #cartContainer></ng-template>

Cart Component .TS

export class CartComponent {
  @Input() public type = 'success';
  @Output() output = new EventEmitter();
}

Cart Component .HTML

<div id="cd-cart" class="speed-in">
<h1 (click)="output.next('output')">Cart {{ type | json}}</h1>
<ul class="cd-cart-items" style="height: 50vh!important;">
<li *ngFor="let CartItem of CartItems; let index = i;">
  <span class="cd-qty">1x</span> CRISTOMORADO MAIZMORADO KG
  <div class="cd-price">S/.7.00</div>
  <a href="#0" class="cd-item-remove cd-img-replace">Remove</a>
</li>

StoreItems Component .TS

constructor(private _sidebarComponent: SidebarComponent){}

private addItem(key: string, value: object) {
  this._sidebarComponent.createComponent(value);
}

StoreItems Component .HTML

<div class="ui-g">
<div *ngFor="let Item of Items" class="ui-g-2">
<a href="javascript:;" (click)="addItem('cart', Items)"><md-card class="item-card">
  <div class="ui-g-2-top">{{ Item.Item_Description }}</div>
  <div class="ui-g-2-bottom">{{ MONEY_CHAR }}{{ Item.ITEM_Sale_Price | number : '1.2-2'}}</div>
</md-card></a>
</div>

LayoutComponent .HTML

<app-sidebar></app-sidebar>

However, when I call addItem() and it calls createComponent(), it doesn't recognize my ViewChild()

Cannot read property 'clear' of undefined

What am I missing?

10
  • when and where do you call addItem ? Commented Jul 21, 2017 at 18:17
  • Please see my edits Commented Jul 21, 2017 at 18:19
  • why do you use ng-template? can you try with ng-container? Commented Jul 21, 2017 at 18:22
  • sure, i can try. but the problem is that the ViewChild from SidebarComponent is not being recognized after injecting it into StoreItems. It works, otherwise. Commented Jul 21, 2017 at 18:25
  • how is SidebarComponent created and injected? can you maybe create a plunker? it's hard to understand your setup Commented Jul 21, 2017 at 18:26

1 Answer 1

1

I have tried something like this and it's working fine for me

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[my-host]',
})
export class MyHostDirective {
  constructor(public viewContainerRef: ViewContainerRef) {
  }
}

import { Component, ViewChild, ComponentFactoryResolver } from '@angular/core';
export class YourComponent{
 @ViewChild(MyHostDirective) myHost: MyHostDirective;
ngAfterViewInit() {
    this.renderDynamicComponents();
  }


  renderDynamicComponents() {
    let component = this.widgetsStoreFactory.getWidgetComponent("ComponentName");
    let componentFactory = this._componentFactoryResolver.resolveComponentFactory(component);
    let viewContainerRef = this.myHost.viewContainerRef;
    viewContainerRef.clear();
    let componentRef = viewContainerRef.createComponent(componentFactory);
    (<IModel>componentRef.instance).YourProperty = "DataToPass";


  }
}


<ng-template my-host>


</ng-template>

Finally please add the dynamic components to the entryComponents of your module

https://angular.io/guide/dynamic-component-loader

https://fromjami.com/2017/06/26/load-components-dynamically-at-runtime-in-angular-4/

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.