Abhishek Kumar
Abhishek Kumar

Reputation: 13

How to hide dynamically created Component in Angular 6

I am loading components dynamically using ComponentFactory on the material stepper and I want to hide the previous component and load a new component on each step.

Current Code- Currently my component is loading on each step but it is destroying the previous component and loading the new components ad I don't want to destroy the previous component. Please find below my code.

ComponentLoad method:

loadComponent(CurrentindexValue: any) {
    
this.currentAdIndex = CurrentindexValue;
this.currentAdIndex = (this.currentAdIndex) % this.wizardValue.component.length;
let adComponentItem = this.wizardValue.component[this.currentAdIndex];
console.log(adComponentItem);
const factories = Array.from(this.componentFactoryResolver['_factories'].keys());
var factoryClass = <Type<any>>factories.find((x: any) => x.name === adComponentItem);
    
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(factoryClass);
           
let viewContainerRef = this.adhost;
viewContainerRef.clear();
let componentRef = this.adhost.createComponent(componentFactory);
    
this.interval = componentRef
}
<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

    import { Component, ViewChild, ViewChildren, Input, OnInit, ComponentFactoryResolver, OnDestroy, ViewContainerRef, AfterViewInit, QueryList, HostBinding } from '@angular/core';
    import { FormGroup, Validators, FormBuilder } from '@angular/forms';
    import { MatStepper } from '@angular/material';
    import { AdComponentItem } from 'src/app/shared/addcomponent';
    import { ActivatedRoute, Router } from '@angular/router';
    import { NewWizardService } from 'src/app/shared/newwizard.service';
    import { Type } from '@angular/core';

    export class Wizard {
        id: number;
        Action: string;
        Title: string[];
        component: string[];

    }
    interface Step {
        label: string;
        id: any;
        componentName: any;
    }

    @Component({
        selector: 'new-wizard',
        templateUrl: './newwizard.component.html',
        styleUrls: ['./newwizard.component.css'],
    })
    export class CreateDatasourceWizardComponent implements OnInit, OnDestroy, AfterViewInit {
        @Input() ads: AdComponentItem[];
        private isButtonVisible = false;
        wizards: Wizard[];
        wizardcountry: string[];
        wizardcomponent: Wizard[];
        wizardValue: Wizard;
        currentIndex: any;
        cmpRef = [];
        currentAdIndex = -1;
        querypvalue: any;
        show: boolean;
        myvar: any;
        @ViewChild('stepper') stepper: MatStepper;
        @ViewChild('adhost', { read: ViewContainerRef }) adhost: ViewContainerRef;
        @HostBinding('hidden')
        isHidden: boolean = false;
        interval: any;

        constructor(private componentFactoryResolver: ComponentFactoryResolver,
            private route: ActivatedRoute, private _router: Router, private wizardData: NewWizardService) {
            this.wizards = [];

        }
        ngOnInit() {
            this.getWizardData();
            this.currentIndex = this.stepper.selectedIndex;
        }

        ngOnDestroy() {
            // this.interval.destroy();
        }
        ngAfterViewInit() {
            this.loadComponent(this.stepper.selectedIndex);
        }

        getWizardData(): void {
            this.wizardData.getData().then((result) => {
                this.wizards = result;

                this.route.queryParams.subscribe(params => {
                    this.querypvalue = params['action'];
                    this.setupWizard(this.querypvalue);
                });
            })
        }

        setupWizard(value: string): void {

            this.wizardValue = this.wizards.find(c => c.Action == value);
            console.log(this.wizardValue);
        }

        loadComponent(CurrentindexValue: any) {
            this.currentAdIndex = CurrentindexValue;
            this.currentAdIndex = (this.currentAdIndex) % this.wizardValue.component.length;
            let adComponentItem = this.wizardValue.component[this.currentAdIndex];
            console.log(adComponentItem);
            const factories = Array.from(this.componentFactoryResolver['_factories'].keys());
            var factoryClass = <Type<any>>factories.find((x: any) => x.name === adComponentItem);

            let componentFactory = this.componentFactoryResolver.resolveComponentFactory(factoryClass);
            let viewContainerRef = this.adhost;
            viewContainerRef.clear();
            let componentRef = this.adhost.createComponent(componentFactory);
            this.interval = componentRef
        }
      
        goBack(stepper: MatStepper) {
            stepper.previous();

            console.log(stepper.selectedIndex);
            this.currentIndex = stepper.selectedIndex
            this.loadComponent(stepper.selectedIndex);
            //this.loadPreviousComponent(stepper.selectedIndex);
        }
        goForward(stepper: MatStepper) {
            stepper.next();
            this.loadComponent(stepper.selectedIndex);
        }
    }
<!-- language: lang-html -->

    <div class="ui-widget-header">
            <span class="field-caption" style="margin-left: 15px;">{{wizardValue.Action}}</span>
        </div>
    <div class="container-fluid">
        
    <div class="row">
    <div class="col-md-12">
        <mat-horizontal-stepper [@.disabled]="true" [linear]="true" #stepper class="stepper-class">
            <mat-step *ngFor="let i of wizardValue.Title">
                <ng-template matStepLabel>{{i}}
                </ng-template>
               
            </mat-step>
        </mat-horizontal-stepper>
    </div>
    </div>
    <div class="row">
        <div class="col-md-12">
    <mat-card>
      <div *ngFor="let i of wizardValue.component let test = index " [id]="i" >
            <!-- <span (onCreate)="onCreate(test)"></span> -->
            
     <ng-template #adhost></ng-template>
     </div>
    </mat-card>
    </div>
    </div>
    <div class="row float-right">
    <div class="col-md-12 stepper-button">
            <button class="btn btn-primary back-button"  (click)="goBack(stepper)" type="button" [disabled]="stepper.selectedIndex===0">Previous</button>
            <button class="btn btn-primary Next-button" (click)="goForward(stepper)" type="button" [disabled]="stepper.selectedIndex===stepper._steps.length-1">Next</button> 
        </div>
    </div>
    </div>

Stepper Image

Upvotes: 1

Views: 3883

Answers (2)

behruz
behruz

Reputation: 588

I think you should save the instance in a public var and just destroy it in the proper condition:

public dynamicComponent: any;

loadComponent(CurrentindexValue: any): void {
    ...
    this.dynamicComponent = this.adhost.createComponent(componentFactory);
    ...
}

Now you can destroy components in a method.

destroyIt(): void {
    this.dynamicComponent.destroy(); 
}

Now you just need to call this method whenever you want.

Upvotes: 1

behruz
behruz

Reputation: 588

you just need to create an input and in your component template use it as *ngIf statement

public dynamicComponent: any;

loadComponent(CurrentindexValue: any) {
    ...
    this.dynamicComponent = this.adhost.createComponent(componentFactory);
    this.dynamicComponent.hided.subscribe(t => {
        this.hided.emit(true);
        // this is for recalling
    })
} 

hideIt(){
    this.dynamicComponent.hide = true; 
}

in your component:

@Input('hide')
set hide(value: boolean) {
this.emidHided();
}
@Output() hided: EventEmitter<>;


public emitHided() {
    this.hided.emit()
}

some fixing is needed in syntax

Upvotes: -1

Related Questions