Base solution for your next web application
Open Closed

Drop down buttons don't work on dynamically loaded content #11294


User avatar
0
astrea created

Prerequisites

  • What is your product version?
    • 11.3.0
  • What is your product type (Angular or MVC)?
    • Angular
  • What is product framework type (.net framework or .net core)?
    • .Net Core 6.0

If issue is about UI

  • Which theme are you using?
    • Metronic (I suppose is 8.0.26 or 8.0.38)
  • What are the theme settings?
    • Default theme (demo 1)

I'm struggling to make the Metronic "kt-menu" dropdown menus to work on the dynamically loaded Cards in the footer sections. Reading the Metronic documentation I was pointed to re-initialize the MenuComponent after the dynamic content is loaded.

Tried with the following code in the mypage.component.ts:

refreshMenus(): void {        
    MenuComponent.reinitialization();
}

I noticed that MenuComponent.reinitialization() actually calls MenuComponent.createInstances('[data-kt-menu="true"]');

I was able to make dropdown menus to work on all Cards only if I manully click on a button which calls the refreshMenus() function which gives me an indication that MenuComponent.reinitialization() works however I cannot make it work with any combination of using the Angular life-cycle hooks (AfterViewInit, AfterContentInit, OnInit, etc) when the pages load.

Is there any other way to solve my challenge?

Any help will be hightly appreciated!


4 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @astrea

    Could you share how you are creating the dynamic items ? Are they loaded in cshtml or via JavaScript ? It would be great if you can share the related code as well.

    I assume, you are calling MenuComponent.reinitialization(); before the items are loaded like you said.

  • User Avatar
    0
    astrea created

    Hi @ismcagdas,

    Let me try to provide the relavant code. I cut as much irrelevant stuff as possible

    lab-details.component.html

    <div [class]="containerClass">
        <div class="row">
            <div class="col-xl-6" *ngFor="let vm of labViewModel?.virtualMachinesViewModels">
                <div class="card mb-7 edulab-vm">
                    <div class="card-footer text-end">
                        <div class="d-flex flex-stack">
                            <div>
                                <button type="button" class="btn btn-sm btn-active-light-primary me-2" data-kt-menu-trigger="click">
                                  BBB2
                                </button>
                              
                                <div class="menu menu-sub menu-sub-lg-down-accordion menu-sub-lg-dropdown menu-rounded-0 py-lg-4 w-lg-225px" data-kt-menu="true">
                                  <div class="menu-item px-3">
                                    <span class="menu-link py-3">
                                      </span>
                                        <span class="menu-title" data-link="#">Some menu title</span>
    </div></div></div></div></div></div></div></div></div>
    

    lab-details.component.ts

    private refreshVirtualApplicationStatusTimer: Observable<number> = timer(0, this.refreshVirtualApplicationStatusIntervalSeconds * 1000);
    
    ngOnInit(): void {
        // Read Lab ID from URL parameter
        this.getLabIdFromUrlParameter().then(labId => {
            this.labId = labId;
            this.loadLabDetails();
    
            // Periodic VAPP refresh
            this.refreshVirtualApplicationStatusSubscription = this.refreshVirtualApplicationStatusTimer.subscribe(async () => {
                await this.refreshVirtualApplication();                
            });
        });
    }
    
    loadLabDetails() {
        this.loadVirtualApplicationAndInitializeUI(this.labId);
    }
    
    private async loadVirtualApplicationAndInitializeUI(labId: string): Promise<LabInstanceDto> {
        return new Promise((resolve, reject) => {
            this.loadVirtualApplication(labId)
                .then(labDto => {
                    if (this.processLabModel(labDto)) {
                        if (this.labViewModel !== undefined) {
                            this._pageTitleService.setPageTitle(this.labViewModel.name);
                        }
                    } else {
                        reject();
                    }
                })
                .finally(() => {                    
                });
        });
    }
    
    private async loadVirtualApplication(vappId: string): Promise<LabInstanceDto> {
        return this._labService.getLabDetails(vappId)
            .toPromise()
            .then((labDto) => {
                return labDto;
            })
            .catch((error) => {
                return null;
            });
    }
    
    private async refreshVirtualApplication(): Promise<LabInstanceViewModel> {
        return this.loadVirtualApplication(this.labId)
            .then(labDto => {
                this.processLabModel(labDto);
                return this.labViewModel;
            })
            .catch(error => {
                abp.log.error(error);
                return null;
            }).finally(() => {
            });
    }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    So, where do you set labViewModel or labViewModel.virtualMachinesViewModels ? As an option, does taht work if you wrap MenuComponent.reinitialization with a setTimeout function ?

  • User Avatar
    0
    astrea created

    Thank you for the tip! Wrapping the function in the setTimeout solved the problem! Also needed to move the refreshMenu function to the labViewModel.

    Kind Regards, Matt