AC component props not updating on time to render component

Hi @patrick,

I’m having issues with props not updating on time for the render function. I believe this wasn’t an issue before the refactor of how AC handles updating the DOM(but I might be wrong).

I have this custom component:

<div is="dmx-jonl_md" id="markdown" dmx-bind:text="getSingleDocument.data.query.translations[0].body" class="js-toc-content text-gray-700 fs-6 mb-10"></div>

And my text prop is binded to the result of a regular SC.

<dmx-serverconnect id="getSingleDocument" url="/api/document/getSingle" dmx-param:id="browser.location.pathparts[1]"></dmx-serverconnect>

Code for the custom component:

dmx.Component('jonl_md', {
    attributes: {
        text: { type: String, default: '' },
    },
    render: function (node) {
        console.log(this.props)
        node.innerHTML = window.markdownit().render(this.props.text);
    }
});

this.props.text is empty for when it’s going to be rendered for the first time(which is expected) but when the data is available it won’t rerun and AC won’t refresh the DOM.

Will this work? I think you mentioned something that the update function no longer works or shouldn’t be used?

update: function (props) {
        if (this.props.text && (props.text != this.props.text)) {
            this.$node.innerHTML = window.markdownit().use(window.markdownItAnchor, {
                slugify: s => slugify(s),
                permalink: window.markdownItAnchor.permalink.headerLink({ renderHref: function (slug) { return `${window.location.pathname}#${slug}` } })
            }).render(this.props.text);
            this.dispatchEvent('rendered');
        }
    }

@patrick any advice on this?

Also, what is the purpose of the nextTick() function?

The render method is only called once when the component is rendered. The update method is called when any data is updated.

The nextTick is a very small delay, just like requestAnimationFrame or setTimeout, only a bit shorter delay.

All is good Patrick. I mixed in my head several concepts that were making the component behave in unwanted ways and I thought it could have something to do with the last updates de AC framework to avoid updating components more than strictly needed.

@patrick “notherone”

If I want the update to run only when the binding of an attribute changes should I check if an element in the props set exists?

if (props.has('attribute'))

Checking other components it seems so but if there is another way let me know please.

And also, do I need to pass the node to the update function in order to read the props set?

update: function (node, props)

If I don’t pass the node I can’t read props.

The update method has indeed 2 arguments, previous it only had 1.

update: function(oldProps, changed) { ... }

In the update function you can access the properties of the component with this.props. The oldProps argument are the previous properties, you can use it to compare the values. New is the changed argument which contains a Set of changed properties, you can use this to see if a property was changed, so you don’t need to compare the values yourself anymore.

Thanks @patrick. Peachy.

I was able to finalise a markdown rendered and a table-of-contents that autogenerates by reading headings of the html. Extremely useful for blogs, documentation, etc.

<div is="dmx-jonl_md_toc" id="toc" content="markdown" class="js-toc toc pt-10" style="width:inherit;"> </div>
<div is="dmx-jonl_md" id="markdown" dmx-bind:text="getSingleDocument.data.query.translations[0].body" class="js-toc-content text-gray-700 fs-6 mb-10" dmx-on:rendered="toc.render(); browser.location.hash ? browser.goto(browser.location.href) : null"></div>

@george I would gladly release this to the public once the AC extensibility is resumed. Just saying :slight_smile:

4 Likes