Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • npack 42 posts 288 karma points
    Aug 16, 2024 @ 22:43
    npack
    0

    v14 - Javascript question - Calling async function from inside render - Section Just Displays [object Promise]

    Maybe more of a javascript question than an Umbraco question.

    I need to do some async work from inside the render method of my custom dashboard. The render method exposed by EmbElementMixin doesn't seem to be called with an await, so if I change

    render() 
    

    to

    async render()
    

    Now I'm returning a promise which the calling umbraco library isn't awaiting so my Screen just shows [object Promise] instead of my html.

    I've tried a half dozen ways of returning html that depends on an async value, and while I can certainly get my code to execute and build an html string I'm not sure how to return that string from inside a .then() callback function since callbacks themselves return promises.

    export default class ExternalBackOfficeElement extends UmbElementMixin(LitElement) {
        iFrameSrc = "";
    
        render() {
            return this.fetchIFrameUrl().then(() => {
    
                return html`
                <div style="width:100%;height:100%;">
                    <iframe src="${this.iFrameSrc}?iFrame=yes" style="width:100%;height:100%;border:none;">
                </div>
                `;
        }); 
    }
    

    }

    Anybody have a suggestion?

  • Huw Reddick 1929 posts 6677 karma points MVP 2x c-trib
    Aug 17, 2024 @ 08:51
    Huw Reddick
    100
  • Huw Reddick 1929 posts 6677 karma points MVP 2x c-trib
    Aug 19, 2024 @ 09:23
    Huw Reddick
    0

    I believe it should be done like below (but don't take my word for it.

    render() {
    
    return html `<umb-body-layout header-transparent header-fit-height>
                <section id="settings-dashboard" class="uui-text">
                <uui-form><uui-box><form id="MyForm" name="myForm" @submit=${this.handleFormSubmit}>${this.renderPollProps()}
    

    ${this.renderPollProps()} is an async function

    async renderPollProps() {
    
        fetchPolls(Number(this.pollid)).then(data => {
            //console.log(data);
            let htmlData =`
            <uui-form-layout-item>
                <uui-label for="Question_${data.id}" slot="label" required="">Question</uui-label>
                <uui-input id="Question_${data.id}" name="question" type="text" label="Question" required="" pristine="" auto-width="" value="${data.name}"></uui-input>
                <uui-input id="qid" name="qid" type="text" label="Id" pristine="" value="${data.id}" style="display:none;"></uui-input>
                <uui-input id="answercount" name="answercount" type="text" label="answercount" pristine="" value="${data.answers.length}" style="display:none;"></uui-input>
            </uui-form-layout-item>`;
        ...
    
  • npack 42 posts 288 karma points
    Aug 19, 2024 @ 15:03
    npack
    0

    Oooh, I think that first link about lit Task is exactly what I needed. I'm still trying to get the import working since it doesn't seem lit/task is exposed in @umbraco-cms/backoffice/external/lit so maybe I need to add lit as a root dependency

    The second example I think I tried, that is, calling my async function from inside the html using return html${this.getSomeUrlAsync()}; and it just returned 'Object.promise' as html text.

    Thanks for your help!

  • npack 42 posts 288 karma points
    Aug 27, 2024 @ 19:11
    npack
    0

    In the end I wasn't able to get the lit Task working even though I think that's the correct solution. I want to be able to import 'Task' from @umbraco-cms/backoffice, but I couldn't find the correct 'import' statement to put at the top of my typescript file.

    Should I be able to do this?

  • npack 42 posts 288 karma points
    23 days ago
    npack
    0

    The solution for me was to use lit 'state' variable and a connectedCallback method that is executed before render is called.

    export default class IFrameSectionElement extends UmbElementMixin(LitElement) {
    
        @state() // Allows an async connected callback method to fill this property before render is called
        private iframeUrl?: string;
    
    
        // Do async work inside this function
        override async connectedCallback() {
            super.connectedCallback();
            this.iframeUrl = await this.getIFrameUrl();
    
        }
    
        render() {
            return html`
                <div class="frame-container">
                    <iframe class="full-frame" src="${this.iframeUrl}" />
                </div>
        `;
        }
    }
    

    Thanks to Jacob Overgaard in https://github.com/umbraco/Umbraco-CMS/discussions/17042

Please Sign in or register to post replies

Write your reply to:

Draft