Premium support for our pure JavaScript UI components


Post by Vinodh Kumar »

Hi Team,

How can we add baseline dropdown with dynamic baseline line options in the Gantt toolbar?

Ex:

Baselines Dropdown with

Latest Baseline
Released Baseline
.....


Post by pmiklashevich »

You refer to gantt/examples/baselines demo?

Снимок экрана 2021-06-14 в 11.40.07.png
Снимок экрана 2021-06-14 в 11.40.07.png (75.39 KiB) Viewed 687 times

Whenever you need to have dynamic data, please think of using a Store. And a UI component that consumes the store, like Combo. It can be configured with multiSelect if needed.

Pavlo Miklashevych
Sr. Frontend Developer


Post by Vinodh Kumar »

Thanks, pmiklashevich

But in gantt/examples/frameworks/angular/advance example toolbar is loading from GanttToolbar.js can you please provide if there is any example how to use the store for loading dynamic data?


Post by pmiklashevich »

You can do the following:

  1. Setup a combo and add a handler for baseline selection

    //Gantt/examples/frameworks/angular/advanced/src/app/lib/GanttToolbar.js
        onBaselineChange({ source : combo, value }) {
            console.log(
                `Baseline ${value} is selected`,
                combo.record,
                this.gantt
            );
        }
    
        static get configurable() {
            return {
                items : [
                    {
                        type         : 'combo',
                        ref          : 'baselinesCombo',
                        editable     : false,
                        valueField   : 'id',
                        displayField : 'name',
                        onChange     : 'up.onBaselineChange'
                    },
    
  2. Setup a store, assign it to the combo, and load the data

    //Gantt/examples/frameworks/angular/advanced/src/app/gantt/gantt.component.ts
    import { Component, AfterViewInit, ViewChild } from '@angular/core';
    import { BryntumGanttComponent } from '@bryntum/gantt-angular';
    import { AjaxStore } from '@bryntum/gantt/gantt.lite.umd.js';
    import ganttConfig from './gantt.config';
    
    @Component({
        selector    : 'app-gantt',
        templateUrl : './gantt.component.html'
    })
    export class GanttComponent implements AfterViewInit {
        ganttConfig = ganttConfig;
    
    @ViewChild('gantt') ganttComponent: BryntumGanttComponent;
    
    ngAfterViewInit() {
        const gantt = this.ganttComponent.instance;
    
        const store = new AjaxStore({
            readUrl : 'test',
            // Hardcoded for the showcase. See "load" call at the end of the function.
            data : [
                { id : 1, name : 'foo' },
                { id : 2, name : 'bar' }
            ]
        });
    
        // @ts-ignore
        gantt.widgetMap.baselinesCombo.store = store;
    
        store.load();
    }
    }
    

    You can do it at any place of your choice. Here is just a quick snippet to show how it works.

    All the best!

Pavlo Miklashevych
Sr. Frontend Developer


Post by Vinodh Kumar »

But I want Menu button style not combo, In the below code menu is static right how can I convert to dynamic. Let me know if it is possible to load baseline data from a local variable instead of using AjaxStore.

 this.baseLineData = [
             { id : 1, name : 'Latest Baseline' },
            { id : 2, name : 'Released Baseline ' }
        ];
{
                type      : 'button',
                text      : 'Show baseline',
                icon      : 'b-fa-bars',
                iconAlign : 'end',
                menu      : [{
                    checked : true,
                    text    : 'Baseline 1',
                    onToggle({ checked }) {
                        toggleBaselineVisible(1, checked);
                    }
                }, {
                    checked : true,
                    text    : 'Baseline 2',
                    onToggle({ checked }) {
                        toggleBaselineVisible(2, checked);
                    }
                }, {
                    checked : true,
                    text    : 'Baseline 3',
                    onToggle({ checked }) {
                        toggleBaselineVisible(3, checked);
                    }
                }]
            },
            
function toggleBaselineVisible(index, visible) { gantt.element.classList[visible ? 'remove' : 'add'](`b-hide-baseline-${index}`); }

Post by pmiklashevich »

It is almost the same, just need to specify the button, and generate menu items dynamically:

//Gantt/examples/frameworks/angular/advanced/src/app/lib/GanttToolbar.js
    onBaselineToggle({ item, checked }) {
        console.log(
            `Baseline ${item.record.id} is toggled`,
            checked,
            item.record,
            this.gantt
        );
    }

static get configurable() {
    return {
        items : [
            {
                type      : 'button',
                ref       : 'baselinesButton',
                text      : 'Show baseline',
                icon      : 'b-fa-bars',
                iconAlign : 'end'
            },
//Gantt/examples/frameworks/angular/advanced/src/app/gantt/gantt.component.ts
import { Component, AfterViewInit, ViewChild } from '@angular/core';
import { BryntumGanttComponent } from '@bryntum/gantt-angular';
import { Menu } from '@bryntum/gantt/gantt.lite.umd.js';
import ganttConfig from './gantt.config';

@Component({
    selector    : 'app-gantt',
    templateUrl : './gantt.component.html'
})
export class GanttComponent implements AfterViewInit {
    ganttConfig = ganttConfig;

@ViewChild('gantt') ganttComponent: BryntumGanttComponent;

ngAfterViewInit() {
    const gantt = this.ganttComponent.instance;
    // @ts-ignore
    const { baselinesButton } = gantt.widgetMap;

    const baselineData = [
        { id : 1, name : 'Latest Baseline' },
        { id : 2, name : 'Released Baseline ' }
    ];

    baselinesButton.menu = new Menu({
        autoShow : false,
        items    : baselineData.map(baseline => ({
            checked  : true,
            text     : baseline.name,
            record   : baseline,
            onToggle : 'up.onBaselineToggle'
        }))
    });
}
}

Depends on your requirements you can setup a click handler in GanttComponent. I just show you different options.

Cheers!

Pavlo Miklashevych
Sr. Frontend Developer


Post by Vinodh Kumar »

Thanks, It's working


Post by Vinodh Kumar »

But, how can we customize baseline names in tooltips?

For suppose I have 2 baselines Latest Baseline & Released Baseline, how can we display those names in the tooltip instead of baseline 1, baseline 2. I attached a screenshot can you please check once.

Attachments
bryntum-gantt-baseline.png
bryntum-gantt-baseline.png (73.98 KiB) Viewed 652 times

Post by pmiklashevich »

Please see: https://www.bryntum.com/docs/gantt/#Gantt/feature/Baselines#config-template
You can check out how it's done in Gantt/examples/baselines/app.js

    features : {
        baselines : {
            // Custom tooltip template for baselines
            template(data) {
                const
                    me           = this,
                    { baseline } = data,
                    { task }     = baseline,
                    delayed      = task.startDate > baseline.startDate,
                    overrun      = task.durationMS > baseline.durationMS;

            let { decimalPrecision } = me;

            if (decimalPrecision == null) {
                decimalPrecision = me.client.durationDisplayPrecision;
            }

            const
                multiplier      = Math.pow(10, decimalPrecision),
                displayDuration = Math.round(baseline.duration * multiplier) / multiplier;

            return `
                <div class="b-gantt-task-title">${StringHelper.encodeHtml(task.name)} (${me.L('baseline')} ${baseline.parentIndex + 1})</div>
                <table>
                <tr><td>${me.L('Start')}:</td><td>${data.startClockHtml}</td></tr>
                ${baseline.milestone ? '' :   `
                    <tr><td>${me.L('End')}:</td><td>${data.endClockHtml}</td></tr>
                    <tr><td>${me.L('Duration')}:</td><td class="b-right">${displayDuration + ' ' + DateHelper.getLocalizedNameOfUnit(baseline.durationUnit, baseline.duration !== 1)}</td></tr>
                `}
                </table>
                ${delayed ? `
                    <h4 class="statusmessage b-baseline-delay"><i class="statusicon b-fa b-fa-exclamation-triangle"></i>${me.L('Delayed start by')} ${DateHelper.formatDelta(task.startDate - baseline.startDate)}</h4>
                ` : ''}
                ${overrun ? `
                    <h4 class="statusmessage b-baseline-overrun"><i class="statusicon b-fa b-fa-exclamation-triangle"></i>${me.L('Overrun by')} ${DateHelper.formatDelta(task.durationMS - baseline.durationMS)}</h4>
                ` : ''}
                `;
        }
    },

Pavlo Miklashevych
Sr. Frontend Developer


Post by pmiklashevich »

Please always ask one question per thread.

Pavlo Miklashevych
Sr. Frontend Developer


Post Reply