Adam Smock
Adam Smock

Reputation: 61

How would I change the background color of a list item upon click? (ES6 & Polymer)

I've cloned a repository which focuses on creating a To-Do application using ES6 and Polymer 3. I'm trying to implement a button which turns the background color containing a string green upon click. I've tried doing this, but I keep failing to get the desired result.

Example code:

 static get properties() {
    return {
      list: {type: Array},
      todo: {type: String},
    };
  }
  constructor() {
    super();
    this.list = [
      this.todoItem('buy cereal'),
      this.todoItem('buy milk')
    ];
    this.todo = '';
    this.createNewToDoItem = this.createNewToDoItem.bind(this);
    this.handleKeyPress = this.handleKeyPress.bind(this);
    this.handleInput = this.handleInput.bind(this);
  }

  todoItem(todo) {
    return {todo}
  }

  createNewToDoItem() {
    this.list = [
      ...this.list,
      this.todoItem(this.todo)
    ];
    this.todo = '';
  }

  //Right here is where I tried to implement the background color change.
  checkItem() {
    checkItem = document.getElementById('checkItem'),
    checkItem.addEventListener('click', () => {
      this.list = this.list.filter(this.todo)
      document.body.style.backgroundColor = 'green';
    });
  }

  deleteItem(indexToDelete) {
    this.list = this.list.filter((toDo, index) => index !== indexToDelete);
  }

  render() {
    return html`
    ${style}
    <div class="ToDo">
      <h1>Grocery List</h1>
      <h1 class="ToDo-Header">What do I need to buy today?</h1>
      <div class="ToDo-Container">

        <div class="ToDo-Content">

          ${repeat(
            this.list,
            (item, key) => {
              return html`
                <to-do-item
                  item=${item.todo}
                  .deleteItem=${this.deleteItem.bind(this, key)}
                ></to-do-item>
              `;
            }
          )}
        </div>

I'd be eternally thankful if someone helped me out. I've created two JSFiddle links which show the code I've worked on thus far:

Link 1: https://jsfiddle.net/r2mxzp1c/ (Check line 42-49)

Link 2: https://jsfiddle.net/zt0x5u94/ (Check line 13 & 22-24)

Upvotes: 1

Views: 341

Answers (2)

stevs
stevs

Reputation: 21

You should try to make the reactive templating work for you by defining presentation details in terms of your element's properties.

For example, this is a stripped-down approach to the same problem:

class TestElement extends LitElement{
  static get properties() {
    return {
      'items':  { 'type': Array }
    };
  }

  constructor() {
    super();
    // set up a data structure I can use to selectively color items
    this.items = [ 'a', 'b', 'c' ].map((name) =>
      ({ name, 'highlight': false }));
  }

  render() {
    return html`<ol>${
      this.items.map((item, idx) =>
        html`<li
          @click="${ () => this.toggle(idx) }"
          style="background: ${ item.highlight ? '#0f0' : '#fff' }">
            ${ item.name }
        </li>`) 
    }</ol>`;
  }

  toggle(idx) {
    // rendering won't trigger unless you replace the whole array or object
    // when using properties of those types. alternatively, mutate with the
    // usual .push(), .splice(), etc methods and then call `this.requestUpdate()`
    this.items = this.items.map((item, jdx) =>
      jdx === idx ? { ...item, 'highlight': !item.highlight } : item
    );
  }
}

https://jsfiddle.net/rzhofu81/305/

I define the template such that the elements are colored the way I want depending on an aspect of their state (the "highlight" attribute of each entry in the list), and then I focus the interaction on updating the state to reflect what the user is doing.

Upvotes: 0

merlosy
merlosy

Reputation: 607

I'm not sure about the approach. But this link might help you https://stackblitz.com/edit/web-components-zero-to-hero-part-one?file=to-do-app.js

from this guy: https://stackblitz.com/@thepassle

Upvotes: 1

Related Questions