Use of jQuery in a dashboard widget

Hi there,

I am developing a dashboard widget to control an air conditioner.
I wanted to do something fancy and found a JavaScript library that helps with round sliders.

The mentioned library is https://roundsliderui.com/ and as it’s documentation (Documentation - roundSlider (A free jQuery plugin)) says, it’s as simple as calling the constructor method: $("#slider").roundSlider();.

This works fine, but some times I got errors in my console that made this widget fail.

image

Could this be caused by the jQuery sintaxis?
Perhaps it is trying to load this before the DOM and not finding it?

I am quite lost debugging this as sometimes it works and sometimes it does not.

I think it’s important to mention that I’m doing all this within an angular directive, in a custom html widget.
My instance is in v.6.1.1-beta.

Thank you in advance,

Hi @SRG

It may be due to the script not being loaded when the function roundSlider is called.

You can lazy load the scripts doing something like this.

angular.module('helloWidget', [])
.directive('helloWidget', function () {
    return {
        restrict: 'EA',
        scope: {
            source : "=",
            ts:      "=",
            value:   "="
        },
        templateUrl: function(){
            let url = document.querySelector("script[src*='helloWidget.js']");
            return url.src.replace('.js','.html');
        },
        controller: ["$scope", function($scope){
            console.log("controller initialized! scope is", $scope);

            const widgetFile = 'helloWidget.js';
            let url = document.querySelector(`script[src*='${widgetFile}']`);

            function loadLibraries(){
                return new Promise((resolve, reject) => {

                    let dependencies =
                        [
                            url.src.replace(widgetFile, 'static/js/jquery.min.js'), // local scripts
                            'https://code.jquery.com/jquery.min.js' // remove scripts
                        ];
                        
                    let resolved = 0;

                    dependencies.forEach(function(src) {
                        let script = document.createElement('script');
                        script.src = src;
                        script.async = false;

                        // Resolve the promise once the script is loaded
                        script.addEventListener('load', () => {
                            if(++resolved===dependencies.length){
                                resolve(resolved);
                            }
                        });

                        // Catch any errors while loading the script
                        script.addEventListener('error', () => {
                            reject(new Error(`${src} failed to load.`))
                        });

                        document.head.appendChild(script);
                    });
                });
            }
            
            loadLibraries().then((result) => {
               // Write here the logic of the widget

                // listeners for process source changes (if required)
                $scope.$watch('source', function(newVal, oldVal) {
                    console.log("Source has changed:", newVal, oldVal);
                });
            
                // listeners for process value changes (if required)
                $scope.$watch('value', function(newVal, oldVal) {
                    console.log("Value has changed:", newVal, oldVal);
                });
            }).catch((error) => {
                    console.error(error);
            });
            
        }]
    }
});

Hi there,

Tried the code but it gives me a few compile errors because of a few missing closing symbols.
Solving this, my widget never loads.

Could this be solved by setting a timeout for example? I have tried it a few times but even with 3 or 4 seconds it sometimes gets stuck.

Kind regards,

Hi @SRG

I’ve edited the code from before to fix the syntax errors. This is the best solution we’ve found so far, you may be able to solve it with a timeout but as you say, that solution does not always work.

Try with the fixed code and share error codes as well your own code to be able to help you further

Hi @jaimebs ,

I have tried using the modified code and still have some problems loading the dependencies.

Is this URL correct? I don’t have any scripts in my file storage other than this angular directive.
I am loading the resources from html <script> tags.

In my acUnitsManagement.html file:

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>                      
<link href="https://cdn.jsdelivr.net/npm/round-slider@1.6.1/dist/roundslider.min.css" rel="stylesheet" />                                
<script src="https://cdn.jsdelivr.net/npm/round-slider@1.6.1/dist/roundslider.min.js"></script>

The errors shown in the image correspond to the catch and reject methods in the `loadLibraries’ function.

As I understand it, perhaps I need to set these dependencies not in a script tag but in the dependencies variable?

Thank you,

Note:

By modifying the dependencies variable, works perfectly fine!
Just had to set the right ones from the script tags

let dependencies = ['https://code.jquery.com/jquery-3.6.0.min.js',
                            'https://cdn.jsdelivr.net/npm/round-slider@1.6.1/dist/roundslider.min.js'];

Thanks for your time @jaimebs!

Hi @SRG

Indeed, those dependencies were just examples on how to load either local scripts and remote scripts.

Glad it worked!