javascriptaureliaaurelia-templating

Execute function after content has been dynamically loaded in Aurelia


I am using Aurelia.

I have a post route, that displays a post given the passed id. The server compiles the Markdown used to write the post to HTML, and I am loading this content in my template using:

<div innerHTML.bind="post.content"></div>

// in the activate() function
client
    .fetch(`api/post/${params.id}`)
    .then(res => res.json())
    .then(data => {
        this.post = data;

        // this is the workaround I am currently using
        setTimeout(this.displayLineNumbers, 200);
    });

I couldn't find any way to execute a function when the content had been attached to the view. If I only use:

this.post = data;
this.displayLineNumbers();

It will fail, as the content has not been attached yet, thus the elements my function is meant to change are not available yet. The current workaround I am using is to wait 200ms and then execute the function.

Is there any way (event or function) to know when dynamically loaded content is attached? Or maybe another way of templating the content than innerHTML.bind?


Solution

  • Technically Aurelia has attached itself to the DOM and knows nothing about what you're putting into the page at this stage. However, this sounds like a candidate for the Task Queue. I also remember there being an event you could attach to primarily aimed at e2e testing called aurelia-composed but I've never needed or looked into that.

    The Task Queue allows you to push tasks to the bottom of the task queue that Aurelia uses to prioritize tasks such as if/show bindings and whatnot. I believe this might do what you want it to do.

    import {TaskQueue} from 'aurelia-framework';
    
    activate() {
    client
        .fetch(`api/post/${params.id}`)
        .then(res => res.json())
        .then(data => {
            this.post = data;
    
            this.taskQueue.queueMicroTask(() => {
                this.displayLineNumbers();
            });
        });
    }