MutationObserver does not detect class addition

I have code like this:

Element.el
   (List.concat
       [ if tutorial.enabled then
           [ Element.Events.onClick (TutorialMsg (Tutorial.Current (Just Tutorial.Search1)))
           , Html.Attributes.id (Tutorial.idToString Tutorial.Search1) |> Element.htmlAttribute
           ]

           else
           []
       , case tutorial.current of
           Just current ->
               [ Html.Attributes.classList [ ( Tutorial.observeClass, current == Tutorial.Search1 ) ] |> Element.htmlAttribute ]

           Nothing ->
               []
       ]
   )
   (search isTutorialSearch1 window locale map state.search)

And such code for observer:

module.exports = {
    setup :
    function(app) {
        var containsObserver = app.ports.containsObserver_701aae30_0dc8_4bbf_9943_c5d1e28e6b07;
        var onContains = app.ports.onContains_3feaf185_0702_4f48_a011_ff932defa8df;
        var whatToObserve = document.body;
        if (containsObserver && onContains) {
            var portCallback = function(args) {
                var [ canaryId, className ] = args;
                var observer = new MutationObserver(function(mutations) {
                    console.log(mutations);
                    var elems = document.getElementsByClassName(className);
                    for(var i = 0; i < elems.length; i++) {
                        console.log(elems[i].id);
                        // onContains.send(elems[i].id);
                    }
                    mutations.forEach((mutation) => {

                        if (mutation.type == "childList" && mutation.addedNodes.length > 0) {
                            mutation.addedNodes.forEach(processNode);
                        } else if (mutation.type == "attributes") {
                            console.log(mutation);
                            processNode(mutation.target);

                            if (mutation.target.id == canaryId) {
                                clearInterval(intervalID);
                                mutation.target.remove();
                            }
                        }

                        function processNode(node) {
                            if (node.classList && node.classList.contains(className)) {
                                onContains.send(node.id);
                            }

                        }
                    });
                });

                observer.observe(whatToObserve, {attributes: true, attributeFilter: ['class'], childList: true, characterData: false, subtree:true});

                var newDiv = document.createElement("div");
                newDiv.id = canaryId
                whatToObserve.appendChild(newDiv);
                var intervalID = window.setInterval(() => newDiv.classList.toggle(className), 500);
            };
            containsObserver.subscribe(portCallback);
        }
    }
};

If I run two times this in devconsole:

document.getElementById("Search1").classList.toggle(observeClass)

I will get notification from observer.

Tested both in Firefox and Chrome.

Here Race Condition? Fetching an element by ID of a view which is yet to be rendered it is adviced to use MutationObserver. Now I am not so sure about it.

Also there are answers on so to better use getElementById setTimeout bc observing document.body may be to slow.

So my question is: does anybody experienced this? How to overcome it?

Hello @rofrol,

You’ve created your post under “Learn”. From it’s content it is not entirely clear what you would like to learn. What is your question exactly?

I’ve added question.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.