Our pure JavaScript Scheduler component


Post by bachnx »

hi ! i just using bryntum schedule in angular app ,the component defined by tabcode and display it as a tab on the screen (maximize 10 tab ), when i inject bryntum schedule to 1 angular component , if i show the bryntum schedule in component as a tab then the angular change detection take too long to complete task and make the mouse move , drag, drop animation in bryntum super laggy , but if i open only component have bryntum schedule in another chrom tab (as a new window only show bryntum schedule without any other tab and sidebar , ... ) its smooth as expected like the demo , any solution for this ?


Post by marcio »

Hey bachnx,

Could you provide a sample project with the configuration that you mentioned?

With that description, it is difficult to understand what could be causing the lagging.

Best regards,
Márcio


Post by bachnx »

we are using dynamic tab in angular like this :
in home.component.html:

 <tab *ngFor="let tab of openedTabsObj; let i = index" heading="{{tab.name | localize}}" [active]="tab.active"
        (selectTab)="tab.code ? displayTab(tab.code, $event) : undefined" [removable]="true" (removed)="removeTabHandler(tab)" id="{{i}}">
        <dynamic-tab

      #dynamic_tab
      [tabCode]="tab.code"
      [currentTabCode]="currentTabCode"
      (setShortcuts)="setShortcuts($event)"
      (autoReloadWhenDisplayTab)="autoReloadWhenDisplayTab($event)"
      (changeTabCode)="changeTabCode($event)"
      (removeRegisterNo)="removeRegisterNo($event)"
      [params]="tab.params">
    </dynamic-tab>
  </tab>

here is in home.component.ts:

displayTab(code: string, event?) {
    if (!code) return;
    if (event && code === this.currentTabCode) return;
    // if (this.currentTabCode === TABS.SERVICE_QUOTATION_RECEPTIONIST_APPOINTMENT)  {
    //   const currentTab  = this.tabElements?.find((e) => e.tabCode === this.currentTabCode);
    //   if (typeof currentTab?.componentRef?.instance?.save === 'function') currentTab?.componentRef?.instance?.save();
    // }

// name param is used for tabs that can open multi instances
this.setCurrentTab(code);
setTimeout(() => this.setTitleTab(), 50);

// set custom interval
const currentTab  = this.tabElements?.find((e) => e.tabCode === this.currentTabCode);
if (this.currentTabCode === TABS.SERVICE_DASHBOARD_RECEPTIONIST && typeof currentTab?.componentRef?.instance?.reload === 'function') {
    currentTab?.componentRef?.instance?.reload();
    // this.interval = setInterval(() => {
    //     currentTab?.componentRef?.instance?.reload();
    // }, 60000)
}
else if (this.currentTabCode === TABS.SERVICE_DASHBOARD_ADVISOR && typeof currentTab?.componentRef?.instance?.reload === 'function') {
    currentTab?.componentRef?.instance?.reload();
    // this.interval = setInterval(() => {
    //     currentTab?.componentRef?.instance?.reload();
    // }, 60000)
}
else if (this.currentTabCode === TABS.SERVICE_DASHBOARD_NVPT && typeof currentTab?.componentRef?.instance?.refresh === 'function') {
    if(this.interval){
        clearInterval(this.interval);
    }
    currentTab?.componentRef?.instance?.refresh();

}
else {
    clearInterval(this.interval);
}
  }
  
setTitleTab() { this.openedTabsObj.forEach((tab,i) => { let id = i + "-link"; var a = document.getElementById(id); // Get the first <a> element in the document var att = document.createAttribute('title'); // Create a "class" attribute att.value = this.l(tab.name); // Set the value of the class attribute a.setAttributeNode(att); }); } setCurrentTab(code: string) { this._localStorageService.setItem(AppConsts.STORAGE_KEYS.CURRENT_TAB, code); this.currentTabCode = code; if (code === '') { this._router.navigate(['/']); } else { // No re-assign new ref to data-bound this.openedTabsObj for (const objTab of this.openedTabsObj) { if (objTab.code === code) { if (!objTab.active) objTab.active = true; } else { if (objTab.active === true) objTab.active = false; } } this._localStorageService.setItem(AppConsts.STORAGE_KEYS.OPEN_TABS, this.openedTabsObj); this.runCustomFunction(code); } }

the dynamic-tab.component.ts also get the module path and then render it

private importModule(path: string, params: any) {
        let transformed = this.getMiddlePathAndModuleName(path);
        // console.log(import(`src/app/${transformed.MiddlePath.toLowerCase()}/${transformed.RawModuleName.toLowerCase()}.module`))
        import(`src/app/${transformed.MiddlePath.toLowerCase()}/${transformed.RawModuleName.toLowerCase()}.module`)
            .then((m) => {
                this.renderComponent(m[`${transformed.ModuleName}Module`], params);
                // console.log(m)
            })
            .finally(()=>{
            })
            .catch(async (ex) => {
                abp.notify.warn(ex);
                const chunkFailedMessage = /Loading chunk [\d]+ failed/;
                if (chunkFailedMessage.test(ex)) {
                    await abp.message.confirm(
                        'Đã có phiên bản mới, cần tải lại trang',
                        '',
                        async (confirmed) => {
                            if (confirmed) await window.location.reload();
                        }
                    );
                }
            });
    }
    /**
     *
     * @param module
     */
    private renderComponent(module: any, params: any) {
        const _modFac = this.loadModuleFactorySync(module);
        this.moduleRef = _modFac.create(this.injector);
        const _comp = (_modFac.moduleType as any).getComponent(this.normalizeTabCode(this.tabCode));
        if (_comp) {
            const _compFactory = this.moduleRef.componentFactoryResolver.resolveComponentFactory(_comp);

        if (!this.componentRef) this.componentRef = this.componentPlaceholder.createComponent(_compFactory);

        this.componentRef.instance.autoReloadWhenDisplayTab = this.autoReloadWhenDisplayTab;
        this.componentRef.instance.changeTabCode = this.changeTabCode;
        this.setShortcuts.emit(this.componentRef);
        this.componentRef.instance.removeRegisterNo = this.removeRegisterNo;
        if (this.currentTabCode === TABS.SERVICE_QUOTATION_RECEPTIONIST_APPOINTMENT) this.componentRef.instance.params = { showPopup: true };
        else this.componentRef.instance.params = this.params!.data ? this.params!.data : this.params;

        if (this.componentRef.instance.defaultFocusField) {
            let elementRef = '';
            elementRef = 'input';
            this.componentRef.instance.defaultFocusField[elementRef]!.nativeElement.focus();
        }
        // 2 điều kiện: load các tab đã chỉ định hoặc load tất cả các tab chứa biển số
        const normalReloadTabCondition =  params[this.currentTabCode]
                            && (params[this.currentTabCode]!.reload || params[this.currentTabCode]!.isReloadWhenDisplayTab)
                            && this.componentRef.instance && typeof this.componentRef.instance.reload === 'function'
                            && (!params.tabCodes || params.tabCodes.length === 0 || params!.tabCodes.indexOf(this.currentTabCode) !== -1);
        if (normalReloadTabCondition) {
            // Tab có biển số
            if (this.currentTabCode.includes(('---'))) {
                if (params.paramsForTabHasRegisterNo) {
                    if (this.componentRef.instance.params) this.componentRef.instance.params = Object.assign(this.componentRef.instance.params, params.paramsForTabHasRegisterNo);
                    else this.componentRef.instance.params = params.paramsForTabHasRegisterNo;
                } else {
                    if (this.componentRef.instance.params) this.componentRef.instance.params = Object.assign(this.componentRef.instance.params, params[this.currentTabCode]!.data ? params[this.currentTabCode]!.data: params[this.currentTabCode]);
                    else this.componentRef.instance.params = params[this.currentTabCode]!.data ? params[this.currentTabCode]!.data : params[this.currentTabCode];
                }
            }
            else this.componentRef.instance.params = params[this.currentTabCode];
            this.componentRef.instance.reload();
            // if (!this.currentTabCode.includes(TABS.SERVICE_QUOTATION_PROPOSAL)) {

            // }
        }
        params.paramsForTabHasRegisterNo = undefined;
        params[this.currentTabCode] = undefined;
        this.cdr.detectChanges();
    }
}

other component have nothing special its just a normal component and the component have bryntum scheduler is the same as bryntum scheduler demo


Post by bachnx »

its kinda hard to expland how it work , above is some code about using dynamic tab and render module as a tab , i am trying to split to a smaller example project and then post it in here soon :< (sorry for late reply btw)


Post Reply