Premium support for our pure JavaScript UI components


Post by Shinya Umeshita »

How can we Import other classes such as Column, Column store from bryntum Library specifically in Salesforce LWC?

Is there any example showing how to register a class by extending column for Salesforce LWC.
I have understanding how it works in other frameworks. But have some issue on how i can import column and columnstore in salesforce,

This is the source code that I tried to execute.

// I need to Import Column
// I need to Import Column Store


/**
 * A column showing the status of a task
 *
 * @extends Gantt/column/Column
 * @classType statuscolumn
 */
class StatusColumn extends Column{

    constructor() {
        Promise.all([
            loadScript(this, GANTT + '/gantt.lwc.module.min.js'),
            loadStyle(this, GANTT + '/gantt.material.min.css'),
        ]);

        console.log('Test');
    }

    static get $name() {
        return 'StatusColumn';
    }

    static get type() {
        return 'statuscolumn';
    }

    static get isGanttColumn() {
        return true;
    }

    static get defaults() {
        return {
            // Set your default instance config properties here
            field      : 'status',
            text       : 'Status',
            editor     : false,
            cellCls    : 'b-status-column-cell',
            htmlEncode : false,
            filterable : {
                filterField : {
                    type  : 'combo',
                    items : ['Not Started', 'Started', 'Completed', 'Late']
                }
            }
        };
    }

    //endregion

    renderer({ record }) {
        const status = record.status;

        return status ? {
            tag       : 'i',
            className : `b-fa b-fa-circle ${status}`,
            html      : status
        } : '';
    }
}

ColumnStore.registerColumnType(StatusColumn);

Than you.


Post by Maxim Gorkovsky »

Hello.
If you want to use classes from the static resource it would be impossible to do that with regular import statement. You can do smth like:

await Promise.all([
            loadScript(this, GANTT + '/gantt.lwc.module.min.js'),
            loadStyle(this, GANTT + '/gantt.material.min.css'),
        ]);

// lwc module bundle exposes global `bryntum.gantt` namespace with all the exported classes
const { Column } = bryntum.gantt;

class MyColumn extends Column {...}

We haven't tried using gantt without a static resource, but as I understand it should be possible. You can try to use all
classes directly from the gantt.lwc.module.min.js and not load it as a static resource:

import { Column } from `.../gantt.lwc.module.min.js`;

class MyColumn extends Column {...}

Then you just build this js app and upload it like LWC component.


Post by Shinya Umeshita »

there is a error message saying await keyword is unexpected.
could you give a little more information on how exactly we could register columns in LWC.(A demo maybe).
Or some documentation which outlines how it should be done in Salesforce LWC I found documentations for other platforms which describe this process .
But i could not find it for salesforce . Thank you for your support.

1) // import ColumnStore from '@salesforce/resourceUrl/bryntum_gantt_426/gantt.lwc.module.min.js';
// import Column from '@salesforce/resourceUrl/bryntum_gantt_426/gantt.lwc.module.min.js';

await Promise.all([
    loadScript(this, GANTT + '/gantt.lwc.module.min.js'),
    loadStyle(this, GANTT + '/gantt.material.min.css'),
]);

// New column class to display task priority
class TaskPriorityColumn extends Column {
    // unique alias of the column
    static get type() {
        return 'priority';
    }
    // indicates that the column should be present in "Add New..." column
    static get isGanttColumn() {
        return true;
    }
    static get defaults() {
        return {
            // the column is mapped to "priority" field of the Task model
            field : 'priority',
            // the column title
            text  : 'Priority'
        };
    }
}
// register new column
ColumnStore.registerColumnType(TaskPriorityColumn);

Post by Maxim Gorkovsky »

await can only be used inside async function.

// not supported
await foo();
bar();

// use
foo().then(() => bar());

// or
const baz = async() => await foo();
baz().then(() => bar())

Please refer to this article: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function


Post by Shinya Umeshita »

Thank you , I was able to successfully register a column.
And Now i am looking to improve upon current implementation.

I have 2 queries.

  1. Currently the creation of a custom column class and registering of column class is taking place in the same js file as gantt implementation.
    I would like to separate this out . as in i would like the Creation of column class and registration to be done in a separate js file.
    How should this be done?. Could you outline the process . Like after creating the new js column how should it be included in the js file which takes care of gantt implementation.

  2. Currently the above source code creates a new column called ‘Priority’.
    I want this column to be added into the combo box of ‘addnew’ column.
    How can this be done in salesforce LWC since we are using a minified js version I am not well aware of how this can be done. Is there a way to add new elements(custom columns) into the existing ‘AddNewColumn’.

Thank you.

/* globals bryntum : true */
import { LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import GANTT from '@salesforce/resourceUrl/bryntum_gantt_426';
import GanttToolbarMixin from './lib/GanttToolbar';
import data from './data/launch-saas';
 
export default class Gantt_component extends LightningElement {
  bryntumInitialized = false;
  renderedCallback() {
    if (this.bryntumInitialized) {
      return;
    }
    this.bryntumInitialized = true;
 
    Promise.all([
      loadScript(this, GANTT + '/gantt.lwc.module.min.js'),
      loadStyle(this, GANTT + '/gantt.material.min.css'),
    ])
      .then(() => {
        const { Column, ColumnStore } = bryntum.gantt;
 
        // New column class to display task priority
        class TaskPriorityColumn extends Column {
          // unique alias of the column
          static get type() {
            return 'priority';
          }
 
          // indicates that the column should be present in "Add New..." column
          static get isGanttColumn() {
            return true;
          }
 
          static get defaults() {
            return {
              // the column is mapped to "priority" field of the Task model
              field: 'priority',
              // the column title
              text: 'Priority',
              filterable: {
                filterField: {
                  type: 'combo',
                  items: ['Not Started', 'Started', 'Completed', 'Late'],
                },
              },
            };
          }
        }
 
        // register new column
        ColumnStore.registerColumnType(TaskPriorityColumn);
 
        this.createGantt();
      })
      .catch((error) => {
        this.dispatchEvent(
          new ShowToastEvent({
            title: 'Error loading Bryntum Gantt',
            message: error,
            variant: 'error',
          }),
        );
      });
  }
 
  createGantt() {
    const GanttToolbar = GanttToolbarMixin(bryntum.gantt.Toolbar);
 
    const project = new bryntum.gantt.ProjectModel({
      calendar: data.project.calendar,
      startDate: data.project.startDate,
      tasksData: data.tasks.rows,
      resourcesData: data.resources.rows,
      assignmentsData: data.assignments.rows,
      dependenciesData: data.dependencies.rows,
      calendarsData: data.calendars.rows,
    });
 
    const gantt = new bryntum.gantt.Gantt({
      project,
      appendTo: this.template.querySelector('.container'),
      startDate: '2019-01-12',
      endDate: '2019-03-24',
 
      tbar: new GanttToolbar(),
 
      dependencyIdField: 'sequenceNumber',
      columns: [
        { type: 'wbs' },
        { type: 'name', width: 250 },
        { type: 'startdate' },
        { type: 'duration' },
        { type: 'resourceassignment', width: 120 },
        { type: 'percentdone', showCircle: true, width: 70 },
        {
          type: 'predecessor',
          width: 112,
        },
        {
          type: 'successor',
          width: 112,
        },
        { type: 'schedulingmodecolumn' },
        { type: 'calendar' },
        { type: 'constrainttype' },
        { type: 'constraintdate' },
        {
          type: 'date',
          text: 'Deadline',
          field: 'deadline',
        },
        { type: 'priority' },
        { type: 'addnew' },
      ],
 
      subGridConfigs: {
        locked: {
          flex: 3,
        },
        normal: {
          flex: 4,
        },
      },
 
      columnLines: false,
 
      features: {
        rollups: {
          disabled: true,
        },
        baselines: {
          disabled: true,
        },
        progressLine: {
          disabled: true,
          statusDate: new Date(2019, 0, 25),
        },
        filter: true,
        dependencyEdit: true,
        timeRanges: {
          showCurrentTimeLine: true,
        },
        labels: {
          left: {
            field: 'name',
            editor: {
              type: 'textfield',
            },
          },
        },
      },
    });
 
    project.commitAsync().then(() => {
      // console.timeEnd("load data");
      const stm = gantt.project.stm;
 
      stm.enable();
      stm.autoRecord = true;
 
      // let's track scheduling conflicts happened
      project.on('schedulingconflict', (context) => {
        // show notification to user
        bryntum.gantt.Toast.show(
          'Scheduling conflict has happened ..recent changes were reverted',
        );
        // as the conflict resolution approach let's simply cancel the changes
        context.continueWithResolutionResult(
          bryntum.gantt.EffectResolutionResult.Cancel,
        );
      });
    });
  }
}

Post by alex.l »

Hi Shinya Umeshita,

Currently the creation of a custom column class and registering of column class is taking place in the same js file as gantt implementation.
I would like to separate this out . as in i would like the Creation of column class and registration to be done in a separate js file.
How should this be done?. Could you outline the process . Like after creating the new js column how should it be included in the js file which takes care of gantt implementation.

Check GanttToolbarMixin which is custom class and which you imported. It will be the same way as it done for the toolbar. You'll be needed Column and ColumnStore classes loaded, so you'll have to make a wrapper class then and create the column class and register your column type in wrapper class constructor.

Currently the above source code creates a new column called ‘Priority’.
I want this column to be added into the combo box of ‘addnew’ column.
How can this be done in salesforce LWC since we are using a minified js version I am not well aware of how this can be done. Is there a way to add new elements(custom columns) into the existing ‘AddNewColumn’.

Check docs here: https://bryntum.com/docs/gantt/api/Gantt/column/AddNewColumn
It will be available there if you followed the instruction:

In order to appear in the column combobox list a column class have to fulfill these conditions:

  1. the class should have a static property type with unique string value that will identify the column.
  2. the class should be registered with the call to ColumnStore.registerColumnType.
  3. the class should have a static property isGanttColumn with truthy value.
  4. the class should have a static text property with column name.

Let us know if you have questions!

All the best,
Alex


Post by Shinya Umeshita »

Thank you Maxim and alex.

It was successfully done by GanttToolbarMixin .
I really appreciate your kindness.


Post Reply