admin管理员组

文章数量:1400445

When the page first loads, the delete buttons generated by the code below work as expected. However, if you alter the text in one of the <textarea> elements, the delete button no longer works correctly. How can I fix this?

import { LitElement, html } from 'lit-element';

class MyElement extends LitElement {
  static get properties() {
    return {
      list: { type: Array },
    };
  }
  constructor() {
    super();
    this.list = [
      { id: "1", text: "hello" },
      { id: "2", text: "hi" },
      { id: "3", text: "cool" },
    ];
  }
  render() {
    return html`${this.list.map(item =>
        html`<textarea>${item.text}</textarea><button id="${item.id}" @click="${this.delete}">X</button>`
    )}`;
  }
  delete(event) {
    const id = event.target.id;
    this.list = this.list.filter(item => item.id !== id);
  }
}
customElements.define("my-element", MyElement);

When the page first loads, the delete buttons generated by the code below work as expected. However, if you alter the text in one of the <textarea> elements, the delete button no longer works correctly. How can I fix this?

import { LitElement, html } from 'lit-element';

class MyElement extends LitElement {
  static get properties() {
    return {
      list: { type: Array },
    };
  }
  constructor() {
    super();
    this.list = [
      { id: "1", text: "hello" },
      { id: "2", text: "hi" },
      { id: "3", text: "cool" },
    ];
  }
  render() {
    return html`${this.list.map(item =>
        html`<textarea>${item.text}</textarea><button id="${item.id}" @click="${this.delete}">X</button>`
    )}`;
  }
  delete(event) {
    const id = event.target.id;
    this.list = this.list.filter(item => item.id !== id);
  }
}
customElements.define("my-element", MyElement);
Share Improve this question edited Dec 16, 2019 at 22:02 Max888 asked Dec 13, 2019 at 23:48 Max888Max888 3,8505 gold badges35 silver badges76 bronze badges 4
  • Hm. The odd thing is that the list is correct but displays incorrectly. Look at stackblitz./edit/delete-list-element?file=my-element.js Edit 'hi' to 'hi there', tab out, then delete. The list in the console is correct, the display is not. – Thad Commented Dec 14, 2019 at 20:08
  • 1 Actually displayed list is updated and the content of textarea is also updated (innerHtml shows updated content if you change the list.text), but the content of edited textarea is not updated visually. This same error occurs also with <input type=text>-element. It’s like the browser remembers which input-box is edited and keeps it’s content intact visually after the update. – grohjy Commented Dec 15, 2019 at 4:57
  • 1 Try using the repeat directive. – abraham Commented Dec 16, 2019 at 4:42
  • I agree with @grohjy, the list is actually updated and the elements rendered again, you can see if you inspect, it's just a metter that the browser keeps visually the first two textareas after you remove one. Another proof that is some sort of "cache" is the fact that after re-render you still see what you typed, but since you are not updating this.list everytime it should render with the initial values (and it does if you inspect). – mishu Commented Dec 16, 2019 at 14:55
Add a ment  | 

1 Answer 1

Reset to default 10

I'm not sure of the exact cause, but I think it has to do with the way lit-html decides which DOM elements to remove when rendering a list with fewer items than the previous render. The solution is to use the repeat directive. It takes as its second argument a function that helps lit-html identify which DOM elements correspond to which items in the array:

import { repeat } from 'lit-html/directives/repeat.js'

// ...
render(){
  return html`
    ${repeat(this.list, item => item.id,
      item => html`<textarea>${item.text}</textarea><button id="${item.id}" @click="${this.delete}">X</button><br>`
    )}
  `;
}

本文标签: javascriptLitElement remove item from listStack Overflow