cancel
Showing results for 
Search instead for 
Did you mean: 

Execute JS Local Script inside certain container

Execute JS Local Script inside certain container

Hemingway
Established Member

I've implemented local script which generate table of widgets according to their index.

for (let i = config.count - 1; i >= 0; i--) {
                // Clone group config for composite
                const myConf = shmi.cloneObject(groupConfig);
                // Change the name of the composite, so that they are not all named the same
                myConf.name = 'row-' + i;
                // Set placeholder values of the composite
                myConf.replacers = {
                    itemIndex: i
                };
                // Create the composite dynamically
                groups.push(shmi.createControl("group", holder.element, myConf, "div", "after"));
            }

Now this code insert table dynamicaly after my holder element: list-target container. How to change code to insert table directly to the list-target container?

Hemingway_0-1709024393748.png

Hemingway_1-1709024873721.png

 

 

5 REPLIES 5

webiq-sk
Frequent Contributor

Quick answer: choose the correct widget for "holder". If you post the full code maybe help is easier as exactly the interesting part - how "holder" is defined - has been omitted form the example.

For that using shmi.onReady() is a must, please see the scripting demo for an example on this. 

Hemingway
Established Member

This is my full code, where `list-target` is a container with specified dimensions:

 

(function () {
    const MODULE_NAME = "jsonList",
        ENABLE_LOGGING = false,
        RECORD_LOG = false,
        logger = shmi.requires("visuals.tools.logging").createLogger(MODULE_NAME, ENABLE_LOGGING, RECORD_LOG),
        fLog = logger.fLog,
        log = logger.log,
        module = shmi.pkg( MODULE_NAME );

    // MODULE CODE - START

    /* private variables */

    /* private functions */

    /**
     * get the group template id dynamically by the name and category of
     * the composite, so you don 't have to enter the grouptemplateid hardcoded
     *
     * @param {string} name composite name
     * @param {string} category composite category
     * @returns {string} found grouptemplateID
     */
    function getGroupTemplateByName(name, category) {
        // Get a reference to the existing group configs
        const groupConfig = shmi.requires("shmi.visuals.session.groupConfig"),
            iter = shmi.requires("visuals.tools.iterate.iterateObject");

        let found = null;

        iter(groupConfig, function (group, groupName) {
            if (group.label === name && group.category === category) {
                found = groupName;
            }
        });

        return found;
    }

    /**
     * Implements local-script run function.
     * @param {LocalScript} self instance reference of local-script control
     */
    module.run = function (self) {
        let groups = [];
        const cancelable = shmi.onReady({
            controls: {
                holder: ".list-target"
            }
        }, function (resolved) {
            // Retrieve reference to widgets and config object from "config.js"
            const config = shmi.requires("config").config.list, // gets the config from config.js
                holder = resolved.controls.holder,
                groupTemplateId = getGroupTemplateByName(config.compositeName, config.compositeCategory),
                template = "res://" + groupTemplateId + "/template",
                groupConfig = {
                    "template": template,
                    "groupId": groupTemplateId,
                };

            // Creates as many composites as are in "count"
            for (let i = 0; i < config.count; i++) {
                // Clone group config for composite
                const myConf = shmi.cloneObject(groupConfig);

                // Change the name of the composite, so that they are not all named the same
                myConf.name = 'row-' + i;

                // Set placeholder values of the composite
                myConf.replacers = {
                    itemIndex: i
                };
                // Create the composite dynamically
                groups.push(shmi.createControl("group", holder.element, myConf, "div"));
            }
        });


        /* called when this local-script is disabled */
        self.onDisable = function () {
            self.run = false; /* from original .onDisable function of LocalScript control */

            cancelable.cancel()

            groups.forEach(function (el) {
                shmi.deleteControl(el, true);
            });
            groups = [];
        };
    };


    // MODULE CODE - END

    fLog("module loaded");
})();

 

 

webiq-sk
Frequent Contributor

Please note that holder.element returns the HTML DOMNode, however if you inspect the container HTML element using F12 in your browser you'll find out that there is an additional element - the margin-compensator.

Instead of using the createControl method you should use the widget's own addControl method. This will add it where it belongs.

Hemingway
Established Member

Now, I am creating new LS box.js and I am trying to insert all content into 'box' container, but system displays nothing. Could you please check my box.js?

webiq-sk
Frequent Contributor

A few notes beforehand:

  • you removed the onDisable function - this might break functionality, can cause memory leaks which can crash the browser after hours, days, weeks, months or years - please add it back
  • please add the canceable.cancel() call to the onDisable function, otherwise this will cause memory leaks if you remove the widget(s) the script is waiting for but don't remove the LocalScript
  • whenever you use addControl you have to use deleteControl in the onDisable function to prevent memory leaks
  • It doesn't help putting the LocalScript into a container as it will be added to the HEAD of the HTML page anyway. Location of LocalScript is only relevant inside Panel widgets, i.e. a LocalScript is only rendered when included, e.g. in a screen view only if that screen view is shown. It doesn't hurt though.
  • do not use shmi.ctrl in a LocalScript, because you cannot be sure that the widget has actually been initialized when your LocalScript is executed - you have to add ".box" to the shmi.onReady call

Regarding the issue: when you inspect the generated HTML code you will see that the composite widgets are in there, they are just empty:

webiqsk_0-1709219107598.png

I would start from there and see if it works after setting the script up correctly.

 

Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist