Lit-html: Content generated by asyncAppend disappears when sibling element is updated.

Created on 11 Nov 2018  路  4Comments  路  Source: Polymer/lit-html

Live example with code
https://stackblitz.com/edit/lit-element-example-a4bpvn

Expected Results
Content added through asyncAppend is present after calling the render method when isLoading has a different value.

Actual Results
Content added through asyncAppend disappears after calling the render method when isLoading has a different value.

Most helpful comment

As @cyper8 said, the problem here is that you call contentEmitter.generator() inside the update function, which creates a new async iterator. So asyncAppend is given a new async iterator each time it is called, and so it will clear away whatever the previous async iterator returned.

Move the call out and store the result in a variable so that you only ever create one async iterator:

const contentEmitter = contentEmitterFactory();
const asyncIterator = contentEmitter.generator();

let isLoading = false;
function onMore() {
  isLoading = true;
  update();
  contentEmitter.requestContent().then(() => { 
    isLoading = false;
    update();
  })
}

function update() {
  render(html`
        ${
          asyncAppend(asyncIterator, objs =>
            objs.map(o => {
              return html`
                <h1>${o.title}</h1>
                <p>${o.description}</p>
              `;
            })
          )
        }
        ${
          when(
            isLoading,
            () => html`
              loading...
            `,
            () => html`
              <button @click="${onMore}">more content</button>
            `
          )
        }
      `,
  document.getElementById("test"));
}

update();

All 4 comments

@unrealprogrammer That's because you actually rerender it calling update() again (and again). Just comment out all update()s in onMore. Every your update call recreate the generator instance.

Though I still not quite sure how to make your when work. It seems like all right, but still not changes when isLoaded got changed. Keep the issue - maybe someone here can correct it.

As @cyper8 said, the problem here is that you call contentEmitter.generator() inside the update function, which creates a new async iterator. So asyncAppend is given a new async iterator each time it is called, and so it will clear away whatever the previous async iterator returned.

Move the call out and store the result in a variable so that you only ever create one async iterator:

const contentEmitter = contentEmitterFactory();
const asyncIterator = contentEmitter.generator();

let isLoading = false;
function onMore() {
  isLoading = true;
  update();
  contentEmitter.requestContent().then(() => { 
    isLoading = false;
    update();
  })
}

function update() {
  render(html`
        ${
          asyncAppend(asyncIterator, objs =>
            objs.map(o => {
              return html`
                <h1>${o.title}</h1>
                <p>${o.description}</p>
              `;
            })
          )
        }
        ${
          when(
            isLoading,
            () => html`
              loading...
            `,
            () => html`
              <button @click="${onMore}">more content</button>
            `
          )
        }
      `,
  document.getElementById("test"));
}

update();

@mariusGundersen, now i see! Thanks for clarification!

What a silly mistake of mine. It makes perfect sense.
Thank you very much for explaining it 馃檹

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RyanAfrish7 picture RyanAfrish7  路  4Comments

justinfagnani picture justinfagnani  路  3Comments

lastmjs picture lastmjs  路  5Comments

kaaninel picture kaaninel  路  3Comments

abdonrd picture abdonrd  路  4Comments