Multiple tables dynamically generated

I’m trying to build functionality that dynamically generates models and components. I’m using https://docs.skuid.com/latest/en/skuid/javascript/dynamic-model-component-creation.html as my baseline.

I’m able to build and register all of the models, but I’m running into rendering the of tables.

Here is the JavaScript for my component

var element = arguments[0];
var $ = skuid.$;
var $xml = skuid.utils.makeXMLDoc;
// Grab Opp data
var oppsModel = skuid.$M('Opportunities');
var oppMapByFiscalYear = {};
// Make sure we have the Oppmodel
if (oppsModel !== undefined && oppsModel.data.length > 0) {
    // Loop through opp model and map by fiscal year
    oppsModel.data.forEach(opp => {
        console.log('opp', opp);
        var tmpFiscalYear = (opp.FiscalYear !== undefined)
            ? parseInt(opp.FiscalYear) : undefined;
        console.log('tmpFiscalYear', tmpFiscalYear);
        if (oppMapByFiscalYear[tmpFiscalYear] === undefined) {
            oppMapByFiscalYear[tmpFiscalYear] = [];
        }
        oppMapByFiscalYear[tmpFiscalYear].push(opp);
    });
    console.log('oppMapByFiscalYear', oppMapByFiscalYear);
    // Define our Model(s)
    var fiscalYearModels = [];
    for (var fiscalYear in oppMapByFiscalYear) {
        console.log('fiscalYear', fiscalYear);
        var OppModel = new skuid.model.Model({
            dataSourceName: "salesforce",
            objectName: "Opportunity",
            id: fiscalYear,
            recordsLimit: 0,
            fields: [
                    { id: 'Id' },
                    { id: 'Name' },
                    { id: 'CloseDate' },
                    { id: 'RecordType.Name' },
                    { id: 'FiscalYear' },
                    { 
                        id: 'Commitment', 
                        label: 'Commitment',
                        uiOnly: true, 
                        displayType: 'CURRENCY', 
                        formula: 'IF(MODEL_LOOKUP("CommitmentsByOpp","Total","OppId",{{Id}}) !== undefined, MODEL_LOOKUP("CommitmentsByOpp","Total","OppId",{{Id}}), 0)'
                    },
                    { 
                        id: 'Credit', 
                        label: 'Credit',
                        uiOnly: true, 
                        displayType: 'CURRENCY', 
                        formula: 'IF(MODEL_LOOKUP("CreditsByOpp","Total","OppId",{{Id}}) !== undefined, MODEL_LOOKUP("CreditsByOpp","Total","OppId",{{Id}}), 0)'
                    },
                    { 
                        id: 'OpenReceivable', 
                        label: 'OpenReceivable',
                        uiOnly: true, 
                        displayType: 'CURRENCY', 
                        formula: '{{Commitment}} - {{Credit}}'
                    },
            ]
        });
        fiscalYearModels.push(OppModel);
    }
    // Generate the XML string for the tables
    var tables = [];
    if (fiscalYearModels.length > 0) {
        $.each(fiscalYearModels,function(){
            // Register each of our Models with Skuid
            this.initialize().register();
            console.log('this', this);
            console.log(this.id, oppMapByFiscalYear[this.id]);
            this.adoptRows(oppMapByFiscalYear[this.id]);
            console.log('this.id', this.id);
            console.log('this.data', this.data);
             var xmlDefinition =
                '<skootable uniqueid="' + parseInt(Date.now()) + '" showconditions="false" showsavecancel="false" searchmethod="server" searchbox="false" showexportbuttons="true" pagesize="10" createrecords="false" model="' + this.id + '" mode="read" heading="' + this.id + '">' +
                    '<fields>' +
                        '<field id="Name"/>' +
                        '<field id="CloseDate"/>' +
                        '<field id="RecordType.Name"/>' +
                        '<field id="Commitment"/>' +
                        '<field id="Credit"/>' +
                        '<field id="OpenReceivable"/>' +
                    '</fields>' +
                '</skootable>';
            tables.push(xmlDefinition);
        });
        // Wrap the table XMLx in a wrapper because of XML parsing issues
        var xmlString = '<wrapper uniqueid="' + parseInt(Date.now()) + '">' + tables.join('') + '</wrapper>';
        console.log('xmlString', xmlString);
        
        // Convert to jQuery XML object
        var combinedXML = $xml(xmlString);
        console.log('combinedXML', combinedXML);
        
        element.empty();
        // Render the tables -- TODO: Push data into the tables once we get it to render properly
        $.when(skuid.model.load(fiscalYearModels)).then(function(){
            skuid.component.factory({
               element: element,
               xmlDefinition: combinedXML
            });    
        });
        
    }
}

Hi ericmmg, that’s sounds like a cool idea. We browsed through the community and found another post, very similar. Zach and Conlan provided their solutions as complete page XMLs, so you can create a new Skuid page based on Zach’s XML and check out how he created the table dynamically:
https://community.skuid.com/t/dynamically-create-component-upon-click-of-button

Hope this is helpful for you!
Regards! Luzie