Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot extend classes in UMD version #192

Closed
matsbryntse opened this issue Jan 13, 2020 · 9 comments
Closed

Cannot extend classes in UMD version #192

matsbryntse opened this issue Jan 13, 2020 · 9 comments
Assignees
Labels
bug Something isn't working not reproducible

Comments

@matsbryntse
Copy link
Member

matsbryntse commented Jan 13, 2020

Easily reproducible in Docs, update NavigationTree.js in docs app to:


// docsbrowser uses grid bundle and should not import lib classes
//import '../../../lib/Grid/feature/QuickFind.js';
//import TreeGrid from '../../../lib/Grid/view/TreeGrid.js';

const ns = window.bryntum.grid || window.bryntum.scheduler || window.bryntum.schedulerpro || window.bryntum.gantt;

class DocumentationNode extends ns.Model {
    //region Fields

    static get fields() {
        return [
            // "lineno",
            "classDescription",
            "extends",
            "private",
            "constructor",
            "filename",
            "path",
            "folder",
            "modulePath",
            "description",
            "fullName",
            "href",
            "functions",
            "mixins"
        ];
    }

    // endregion
};

export default class NavigationTree extends ns.TreeGrid {
    static get defaults() {
        return {
            rowHeight : 35
        };
    }

    constructor(config, store) {
        Object.assign(config, {
            hideHeaders : true,
            readOnly    : true,
            emptyText   : '',
            features    : {
                cellEdit : false,
                tree     : {
                    expandOnCellClick : true
                },
                quickFind : { mode : 'grid' }
            },

            store : {
                modelClass : DocumentationNode,
                // sort to display folders on top
                sorters    : [
                    {
                        field     : 'name',
                        ascending : true,
                        fn        : (lhs, rhs) => {
                            // Top level nodes must not be sorted
                            if (!lhs.childLevel && !rhs.childLevel) return 0;

                            const lhsIsLeaf = lhs.isLeaf,
                                rhsIsLeaf = rhs.isLeaf;

                            // Both same type, leaf or parent, allow
                            // default sorter to sort by the name
                            if (lhsIsLeaf === rhsIsLeaf) {
                                return null;
                            }

                            // Parent nodes come first
                            return !lhsIsLeaf ? -1 : 1;
                        }
                    }
                ]
            },
            columns : [
                {
                    text                   : 'Name',
                    field                  : 'name',
                    width                  : 150,
                    type                   : 'tree',
                    collapsedFolderIconCls : 'b-icon b-icon-tree-folder',
                    expandedFolderIconCls  : 'b-icon b-icon-tree-folder-open',
                    renderer               : ({ record, cellElement, rowElement }) => {
                        if (record.data.mixin) {
                            cellElement.classList.add('mixin');
                        }

                        if (record.data.access === 'private') {
                            rowElement.classList.add('private');
                        }

                        return record.name;
                    }
                }
            ]
        });

        super(...arguments);
    }

    buildDocsTree(docsJson) {
        const me = this;
        const rows    = [
                {
                    id       : 'guides',
                    name     : 'Guides',
                    expanded : true,
                    children : me.buildGuideTree(me.guides),
                    isGuide  : true,
                    cls      : 'guide'
                },
                {
                    id     : 'demos',
                    name   : 'Demos',
                    target : '_blank',
                    cls    : 'external-link',
                    href   : window.location.host.includes('bryntum') ? `/examples/${me.product}` : '../examples'
                },
                {
                    id       : 'react',
                    name     : 'React components',
                    expanded : false,
                    cls      : 'react',
                    children : []
                },
                {
                    id       : 'api',
                    name     : 'API docs',
                    expanded : false,
                    cls      : 'api',
                    href     : '#api',
                    children : []
                }
            ],
            parents = {},
            apiDocsData = rows.find(cfg => cfg.id === 'api'),
            reactComponentsData = rows.find(cfg => cfg.id === 'react');

        if (me.product === 'gantt' || me.product === 'schedulerpro') {
            rows.splice(2, 0, {
                id   : 'engineDocs',
                name : 'Scheduling Engine API Docs',
                href : './engine/',
                cls  : 'external-link'
            });
        }

        if (docsJson.classes) {
            apiDocsData.expanded = true;

            for (let cls of docsJson.classes) {
                let parent = me.getParent(parents, apiDocsData.children, cls.folder);

                parent && parent.children.push(cls);
            }
        }

        if (docsJson.components) {
            reactComponentsData.expanded = true;
            apiDocsData.expanded = false;

            for (let component of docsJson.components) {
                let parent = me.getParent(parents, reactComponentsData.children, component.folder);

                parent && parent.children.push(component);
            }
        }

        if (!docsJson.components || !docsJson.components.length) {
            rows.splice(rows.findIndex(cfg => cfg.id === 'react'), 1);
        }

        me.store.data = rows;
    }

    getParent(parents, rows, path) {
        if (!path) return null;
        if (parents[path]) return parents[path];

        let parts = path.split('/'),
            cur   = '',
            parent;

        parts.forEach((part, i) => {
            cur += part;

            let found = parents[cur];
            if (!found) {
                found = parents[cur] = {
                    id       : cur,
                    name     : part,
                    children : []
                };
                if (parent) parent.children.push(found);
                if (i === 0) rows.push(found);
            }

            parent = found;

            cur += '/';
        });

        return parent;
    }

    buildGuideTree(guides) {
        return Object.entries(guides).map(([title, data]) => {
            if (typeof data === 'string') {
                return { id : data, isGuide : true, name : title, fullName : data, cls : 'guide', href : '#' + data };
            }
            else {
                return { name : title, children : this.buildGuideTree(data), cls : 'guide-parent' };
            }
        });
    }
};

See also this forum post: https://forum.bryntum.com/viewtopic.php?t=25985

@matsbryntse matsbryntse added the bug Something isn't working label Jan 13, 2020
@matsbryntse matsbryntse added this to the Grid 3.0.2 milestone Jan 13, 2020
@matsbryntse matsbryntse modified the milestones: Grid 3.0.2, Grid 3.0.3 Jan 29, 2020
@bmblb
Copy link

bmblb commented Feb 11, 2020

Problem:

  1. in the Store class we subclass passed model to avoid exposeProperties to pollute all models
ClassDefEx = class extends ClassDef {};
  1. babel transpiles classes to functions (IE11 support)
  2. instances are created using apply, not new
_babel_runtime_helpers_possibleConstructorReturn...()(this, _babel_runtime_helpers_getPrototypeOf...()(ClassDefEx).apply(this, arguments))
  1. es6 classes cannot be instantiated with apply call

Conclusion: modelClass cannot be defined as es6 class with current UMD bundle due to babel output

Should be possible using older approach with function inheritance.

@bmblb bmblb removed the in progress label Feb 11, 2020
@matsbryntse matsbryntse modified the milestones: Grid 3.0.3, Scheduler 3.0.4, Grid 3.0.4 Feb 12, 2020
@pmiklashevych
Copy link

pmiklashevych commented Feb 18, 2020

If you see error like:

ERROR Error: Uncaught (in promise): TypeError: Class constructor IGanttJob cannot be invoked without 'new'
TypeError: Class constructor IGanttJob cannot be invoked without 'new'

To get it fixed you can try to change target from es2015 (modern) to es5 (legacy) in tsconfig.json
"target": "es5",

@matsbryntse matsbryntse modified the milestones: Grid 3.0.4, Grid 3.1.0 Feb 21, 2020
@matsbryntse matsbryntse modified the milestones: Grid 3.1.0, Grid 3.1.1 Mar 6, 2020
@ghost
Copy link

ghost commented Mar 20, 2020

@pmiklashevich Is there a workaround to this without rebuilding the bundle?

@bmblb
Copy link

bmblb commented Mar 20, 2020

We couldn't figure good workaround for this problem. As you can read in my post above it lies very deep in the code.
You have few options though:

  1. extend model class using old style functions approach
  2. extend model using es 6 class and transpile code with babel
  3. or, depending on usecase, not extend model at all. e.g. if you only need to override fields, you can provide them to store config

@ghost
Copy link

ghost commented Mar 20, 2020

I thought of the first option and tried the answers in this SO post, but I end up with more obscure errors (we are still evaluating Bryntum Gantt so we don't have the source code yet)

Could you give some basic example? Like how to extend bryntum.gantt.TaskModel and override the fields property?

@bmblb
Copy link

bmblb commented Mar 20, 2020

Speaking of using babel, you can write model code in smth like babeljs.io/repl and copy paste result. I made a simple example, see here

Speaking of extending fields, you can use smth like:

new ProjectModel({
  taskStore : {
    fields : [...]
  }
})

@ghost
Copy link

ghost commented Mar 20, 2020

Oh, that's useful! And it works! Thanks a lot! That's a huge amount of code generated though. I understand why the UMD version is so much bigger 😲

About your example, using this:

this.project = new bryntum.gantt.ProjectModel({
    taskStore: {
        fields: [
            { name: 'name', type: 'text' },
            { name: 'effort', type: 'effort'},
            { name: 'startDate', type: 'startdate'},
            { name: 'endDate', type: 'enddate'},
        ]
    }
});

I get this:

gantt.umd.js:10 Uncaught TypeError: _0x3d9678[_0x5bf8(...)] is not a function
    at _0x48c759.setEventStore (gantt.umd.js:10)
    at _0x48c759.construct (gantt.umd.js:10)
    at _0x48c759.construct (gantt.umd.js:10)
    at _0x48c759.construct (gantt.umd.js:10)
    at _0x48c759.construct (gantt.umd.js:10)
    at _0x48c759._0x5eeef4 (gantt.umd.js:10)
    at _0x48c759._0x150b9a (gantt.umd.js:10)
    at _0x48c759._0x2be73f (gantt.umd.js:10)
    at _0x48c759._0x519e31 (gantt.umd.js:10)
    at _0x48c759._0x66af7c (gantt.umd.js:10)

The taskStore config option on ProjectTask is not documented, but is a property though.

@bmblb
Copy link

bmblb commented Mar 20, 2020

Try this:

new ProjectModel({
  taskStore : new TaskStore({
    fields : [...]
  })
})

Also that is invalid field config and with valid field types this definition is basically default behavior. What result are you trying to achieve?
Please start new thread on http://www.bryntum.com/forum and tell us what you are trying to do.

@canonic-epicure
Copy link

No reproducible / not relevant after dropping IE11 support:
https://github.com/bryntum/support/assets/72431/e40eb08b-33c7-40e0-9388-7c5b84b65fea

@canonic-epicure canonic-epicure closed this as not planned Won't fix, can't repro, duplicate, stale Aug 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working not reproducible
Projects
None yet
Development

No branches or pull requests

4 participants