Search code examples
datatableautodesk-forgeviewer

How to create a Data Table from forge viewer


I want to create a table that represents the data from a model that I have loaded in the forge viewer.

I want the table to be in a docking panel, and show the properties for elements in the model (level, name, comment, Area, type name --> for each element [if it has the property]).

I have tried to use the API reference, and create a DataTable, but I did not find examples of how to actually implement it.

Where and when do I need to set the datatable? (after or before creating the docking panel?)

What is the content of the arrays that I should pass in the constructor? (according to the documentation: array of arrays for the rows, and array for the columns. Is the row array, is simply an array that contains the columns arrays?)

This is my current code for the extension that shows the amount to instances in the model for each property that I want to adjust:

class testTest extends Autodesk.Viewing.Extension {
constructor(viewer, options) {
    super(viewer, options);
    this._group = null;
    this._button = null;
}

load() {
    console.log('testTest has been loaded');
    return true;
}

unload() {
    // Clean our UI elements if we added any
    if (this._group) {
        this._group.removeControl(this._button);
        if (this._group.getNumberOfControls() === 0) {
            this.viewer.toolbar.removeControl(this._group);
        }
    }
    console.log('testTest has been unloaded');
    return true;
}


   // The Viewer contains all elements on the model, including categories (e.g. families or part definition), 
//so we need to enumerate the leaf nodes, meaning actual instances on the model.
getAllLeafComponents(callback) {
    this.viewer.getObjectTree(function (tree) {
        let leaves = [];// an empty 'leaf' list that we want to fill wiith the objects that has no mo children
        //dbId== object id
        // for each child that we enumerate from a root, call a code , and finally a true /false flag parameter  that run the function recursivly for all the children of a child.
        tree.enumNodeChildren(tree.getRootId(), function (dbId) {
            if (tree.getChildCount(dbId) === 0) {
                leaves.push(dbId);// if the object has no children--> add it to the list.
            }
        }, true);// the last argument we past ("true") will make sure that the function in the seccond argument ("function (dbId)(...)" ")will run recursively not only for the children of the roots, 
        //but for all the children and childrtn's children.
      

        callback(leaves);//return the leaves 
    });
}

onToolbarCreated() {
    // Create a new toolbar group if it doesn't exist
    this._group = this.viewer.toolbar.getControl('allMyAwesomeExtensionsToolbar');//if there is no controller named "allMyAwesomeExtensionsToolbar" create one
    if (!this._group) {
        this._group = new Autodesk.Viewing.UI.ControlGroup('allMyAwesomeExtensionsToolbar');
        this.viewer.toolbar.addControl(this._group);// add the control to tool bar
    }

  

    // Add a new button to the toolbar group

    this._button = new Autodesk.Viewing.UI.Button('testTest');
    this._button.onClick = (ev) => {
     
                           // Check if the panel is created or not
                           if (this._panel == null) {//check if there is an instance of our pannel. if not- create one
                            this._panel = new ModelSummaryPanel(this.viewer, this.viewer.container, 'modelSummaryPanel', 'Model Summary');
                        }
                        // Show/hide docking panel
                        this._panel.setVisible(!this._panel.isVisible());//cal a method from the parent to show/ hide the panel -->use this to toggle from visible to invisible
                        this._panel.set
                        // If panel is NOT visible, exit the function
                        if (!this._panel.isVisible())
                            return;

                        // First, the viewer contains all elements on the model, including
                        // categories (e.g. families or part definition), so we need to enumerate
                        // the leaf nodes, meaning actual instances of the model. The following
                        // getAllLeafComponents function is defined at the bottom
                        this.getAllLeafComponents((dbIds) => {// now we have the list of the Id's of all the leaves
                       
                            // Now for leaf components, let's get some properties and count occurrences of each value
                            debugger;
                            const filteredProps = ['Level','Name','Comments','Area','Type Name'];
                            // Get only the properties we need for the leaf dbIds
                            this.viewer.model.getBulkProperties(dbIds,filteredProps , (items) => {
                                // Iterate through the elements we found
                                
                                items.forEach((item) => {
                                    
                                    // and iterate through each property
                                    item.properties.forEach(function (prop) {
                                        // Use the filteredProps to store the count as a subarray
                                        if (filteredProps[prop.displayName] === undefined)
                                            filteredProps[prop.displayName] = {};
                                        // Start counting: if first time finding it, set as 1, else +1
                                        if (filteredProps[prop.displayName][prop.displayValue] === undefined)
                                            filteredProps[prop.displayName][prop.displayValue] = 1;
                                        else
                                            filteredProps[prop.displayName][prop.displayValue] += 1;
                                    });
                                });
                                // Now ready to show!
                                // The PropertyPanel has the .addProperty that receives the name, value
                                // and category, that simple! So just iterate through the list and add them
                                filteredProps.forEach((prop) => {
                                    if (filteredProps[prop] === undefined) return;
                                    Object.keys(filteredProps[prop]).forEach((val) => {
                                        this._panel.addProperty(val, filteredProps[prop][val], prop);
                                        this.dt = new DataTabe(this._panel);
                                        this.dt.setData()
                                    });
                                });
                            });
                        });
   


    };
    this._button.setToolTip('Or Levis extenssion');
    this._button.addClass('testTest');
    this._group.addControl(this._button);
}

Autodesk.Viewing.theExtensionManager.registerExtension('testTest', testTest);

Solution

  • We have a tutorial with step-by-step on how to do it.

    Please, refer to Dashboard tutorial, specifically in Data Grid section. In this case, the tutorial uses an external library (Tabulator) to show the data.