octobercms/ajax

Hot controls initialize muliple times

Closed this issue · 1 comments

Hello.
octobercms@main from npm

This issue is not related to #29

Hot controls initialize muliple times, because the container.loadDefinition method first unloads the module and then loads it again
image
https://github.com/octobercms/ajax/blob/main/src/observe/container.js#L35C5-L35C19

But documentation says:

This function is idempotent, so calling it multiple times will take the first seen definition.

Example:

title = "Playground"
url = "/playground/:slug?"
==
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="turbo-cache-control" content="no-cache" />
        <title>Playground</title>
    </head>
    <body>
        <div data-control="playground">
            <a class="btn btn-primary"
                href="{{ 'playground'|page({
                    slug: ''
                }) }}"
                role="button">
                Main page
            </a>
            {% set slug = this.param.slug|number_format + 1 %}
            <a class="btn btn-primary"
                href="{{ 'playground'|page({
                    slug: slug
                }) }}"
                role="button">
                Page "{{ slug }}"
            </a>
        </div>

        <script>
            window.pageId = "{{ this.param.slug|default('main') }}";
        </script>

        <script src="{{ url(mix('js/playground.js')) }}" data-turbo-eval="false"></script>
        {% if this.param.slug %}
            <script src="{{ url(mix('js/playground-page.js')) }}" data-turbo-eval-once="{{ this.param.slug }}-page"></script>
        {% else %}
            <script src="{{ url(mix('js/playground-index.js')) }}" data-turbo-eval-once="index-page"></script>
        {% endif %}
    </body>
</html>

js/playground.js

// This is a common file that is used by all pages of the website and is loaded only once.
require("octobercms/src/framework-bundle");

js/playground-index.js

// here we load a common module that can be used on several pages (but not all at once)
import playground from "./playground/module";

playground(window.pageId);

// below is the code specific to this page
// ...

js/playground-page.js (in this example the files are the same, just to show how it works)

// here we load a common module that can be used on several pages (but not all at once)
import playground from "./playground/module";

playground(window.pageId);

// below is the code specific to this page
// ...

js/playground/module.js

export default function (pageId) {
    oc.registerControl(
        "playground",
        class extends oc.ControlBase {
            init() {}

            connect() {
                console.log(`CONNECT: ${pageId}`);
            }

            disconnect() {
                console.log(`DISCONNECT: ${pageId}`);
            }
        }
    );
}

When loading new pages, the previous script will be triggered first, then the new one
image

As a workaround i was added logic into "shouldLoad" method

export default function (pageId) {
    oc.registerControl(
        "playground",
        class extends oc.ControlBase {
            static get shouldLoad() {
                try {
                    return !oc.importControl("playground");
                } catch (error) {}

                return true;
            }
...

This function is idempotent, so calling it multiple times will take the first seen definition.

This statement appears to be false. It should be

This function can be called multiple times, and calling it multiple times will take the last seen definition.

The docs have been updated here:
octobercms/docs@8541e2b