JS integration with OutSystems Events

Hi all,

I'm developing a JS integration with OutSystems Events and for this, I need to use the osAjaxBackend from this thread. The purpose is to initialize a widget when DOM is ready or when the element is ready (because of IFs, the content could not be available yet). Bellow is a code's snippet with the relevant parts:

//When DOM is Ready
    if( Checks the element is on DOM ) {
        lateLoadScrollInit();
    }
    else {
        osAjaxBackend.BindAfterAjaxRequest( lateLoadScrollInit );
    }
....

function lateLoadScrollInit() {
     ...
    //tests element exists and has elements
    if( <Condition> ) {
        //remove event listener and then trigger the Outsystem
        osAjaxBackend.UnbindAfterAjaxRequest( lateLoadScrollInit );
        <list>.forEach(function ( scroll_area ) {
            TriggerEvents(<triggerid>, scroll_area.id);
        })
    }
    return true;
}

The problem here is that the event isn't being removed and is causing a loop because after I Trigger the event from JS I need to refresh an area in the DOM. 


Edit

The issue only occurs when the JS WebBlock is the Pattern Weblock wich use it if it's placed directly in the page footer, it works as expected. I have a list with this pattern (that is behind an IF to show the list of a blank slate when there are no elements in the list), which I suspect is causing the issue. Should OutSystems only include 1 js sheet from the widget instead of N? 


Cheers,

Hi João,

As far as I'm aware, OutSystems creates a separate JS file for every Javascript property of a Web Block/Screen. For other JavaScript usages (namely in Expressions), it is going to end up embedded in the HTML directly.

Hope this helps!

Jorge Martins wrote:

Hi João,

As far as I'm aware, OutSystems creates a separate JS file for every Javascript property of a Web Block/Screen. For other JavaScript usages (namely in Expressions), it is going to end up embedded in the HTML directly.

Hope this helps!

Hi Jorge,

I though OutSystems would optimize that JS sheet in lists by only importing once because I don't see a reason to do it multiple times if the Javascript described is the same. I usually tend to avoid adding Javascript in expressions so I can cache it in the browser and I think its easier to maintain. 

So, what I did was, created a web block with the needed JS and added to the page's footer.


Cheers.

João,

You got me wrong... as far as I known the platform creates one file for each JavaScript property in each web block/screen definition.

If you instantiate your web block multiple times on the same parent web block/screen, it should only load that file once (adds a single <link> tag to the <head>). If you use that same web block in different web screens, the URL for the file is the same in all screens, so the browsers can cache it after fetching it for the first screen that uses it.

Also, just so we're clear, osAjaxBackend.BindAfterAjaxRequest() and osAjaxBackend.UnbindAfterAjaxRequest() are undocumented APIs that may change in the future and that you use at your own risk.

Back to your issue/report, is there no other embedded code that could be executing every time you render your JS web block?

Hi João and Jorge,

The platform only add 1 time each script, independently on how many blocks you have in your page.

What could be causing this, would be if you are invoking the method that does the following part, in the html:

    if( Checks the element is on DOM ) {
        lateLoadScrollInit();
    }
    else {
        osAjaxBackend.BindAfterAjaxRequest( lateLoadScrollInit );
    }

If that would be the case, you'd be appending 1 listener per element in the list.

I'm not entirely sure if this helps you out.

If not, please let me know.

Cheers,

RG

Hi all!

@Jorge, first things first, I do know those APIs are undocumented and I'm aware of the risks, but thanks for the reminder anyway :)

Back to the issue at hand, I was almost sure that's how the web blocks are handled, but this behavior caught me off guard, which was suggesting that the JS was being executed per web block.


@Ruben, that chunk of code is being invoked by an event listener, 'DOMContentLoaded', like you were suggesting, or is being attached to the after ajax refresh, in case the HTML needed isn't being loaded into the DOM right away (in some cases are it might be behind an IF statement). I will try to isolate the issue in two pages, one with the JS code in the footer and the other in the component that uses the JS, and will share the code and the URL later.

Thanks for your help and cheers,