Litelement — сортировка таблиц отображает неправильные значения

#javascript #sorting #checkbox #styling #lit-element

#javascript #сортировка #флажок #стиль #lit-элемент

Вопрос:

Я пытаюсь отсортировать таблицу HTML на основе ее значений в моем элементе Lit. Однако я столкнулся с проблемой с моим компонентом. Вот обзор моей таблицы; введите описание изображения здесь

Проблема

В этом приложении вам нужно иметь возможность сортировать по каждому заголовку таблицы. Однако элементы, которые считаются «выполненными», должны быть перемещены в нижнюю часть таблицы. Моя проблема возникает всякий раз, когда я отмечаю элемент как выполненный. В следующем примере я отмечу верхнюю задачу (задача: 123) как выполненную. Ожидаемое поведение заключается в том, что задача перемещается в нижнюю часть таблицы с включенным флажком. Однако это не то, что является результатом на данный момент.

введите описание изображения здесь

Как вы можете видеть, элемент todo с задачей 123 перемещается в низ. Однако задача с задачей 456 также помечается флажком. Это нежелательное поведение, и я не знаю, что его вызывает. Вы также можете видеть, что цвета неверны (это некоторый стиль, чтобы показать вам, что измененное задание сохраняется, желтый = сохранение, зеленый = сохранено и красный = ошибка).

Вещи, которые я пробовал

Поскольку я не знаю, что именно вызывает эту проблему, я не знаю, что мне делать. Я дал все свои идентификаторы inputs / rows / td, чтобы убедиться, что ничего не перепутано, но, похоже, это не работает.

Код

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

class TableList extends LitElement {
    static get properties() {
        return {
            data: {
                type: Array
            },
            primaryKey: {
                type: String
            },
            defaultSortKey: {
                type: String
            }
        };
    }

    set data(value) {
        let oldValue = this._data;
        this._data = [ ... value];
        this.sortByHeader();
        this.requestUpdate('data', oldValue);
    }

    get data() {
        return this._data;
    }
    
    async edit(entry, key, event) {
        this.shadowRoot.getElementById('entry'   entry[this.primaryKey].value).classList.remove('saved');
        this.shadowRoot.getElementById('entry'   entry[this.primaryKey].value).classList.remove('error');
        this.shadowRoot.getElementById('entry'   entry[this.primaryKey].value).classList.add('saving');

        if (entry[key].type === "checkbox") {
            entry[key].value = event.target.checked;
        } else {
            entry[key].value = event.target.value;
        }

        if (await update(entry)) {
            this.shadowRoot.getElementById('entry'   entry[this.primaryKey].value).classList.remove('saving');
            this.shadowRoot.getElementById('entry'   entry[this.primaryKey].value).classList.add('saved');

            setTimeout(() => {
                this.shadowRoot.getElementById('entry'   entry[this.primaryKey].value).classList.remove('saved');
            }, 1000);
        } else {
            this.shadowRoot.getElementById('entry'   entry[this.primaryKey].value).classList.remove('saving');
            this.shadowRoot.getElementById('entry'   entry[this.primaryKey].value).classList.add('error');

            setTimeout(() => {
                this.shadowRoot.getElementById('entry'   entry[this.primaryKey].value).classList.remove('error');
            }, 5000);
        }
    }

    sortByHeader(key) {       
        if (key === undefined) {
            key = this.defaultSortKey;
        }

        let oldValue = this.data;
        this._data = [ ... this.data.sort((a, b) => {
            return a[this.defaultSortKey].value - b[this.defaultSortKey].value 
                        || a[key].value - b[key].value;
        })];

        this.requestUpdate('data', oldValue);
    }

    renderHeaders() {
        let keys = Object.keys(this.data[0]);

        return keys.map(key => html`
            ${this.data[0][key].visible ?
                html`
                    <th id="${'header'   key}" @click="${() => this.sortByHeader(key)}">
                        ${key}
                    </th>
                `: ''
            }
        `)
    }

    renderRows() {
        return this.data.map(entry => html`
        <tr id="${'entry'   entry[this.primaryKey].value}">
            ${Object.keys(entry).map(key => html`
                ${entry[key].visible amp;amp; !entry[key].editable ?
                    html`<td>${entry[key].value}</td>`
                    : ``
                }
                ${entry[key].visible amp;amp; entry[key].editable ?
                    html`<td id="${'td'   key   entry[this.primaryKey].value}">
                            <input
                                id="${'input'   key   entry[this.primaryKey].value}"
                                name="${'input'   key   entry[this.primaryKey].value}"
                                type="${entry[key].type}"
                                ?checked="${entry[key].value}"
                                value="${entry[key].value}"
                                @change="${(event) => {
                                    this.edit(entry, key, event)
                                }}"
                            />
                        </td>`
                    : ``
                }
            `)}
        </tr>
        `)
    }

    render() {
        return html`
            <table id="table-list">
                <thead>
                    <tr>
                        ${this.renderHeaders()}
                    </tr>
                </thead>
                <tbody>
                    ${this.renderRows()}
                </tbody>
            </table>
      `;
    }

    static get styles() {
        return css`
            table {
                width: 100%;
                border-collapse: collapse;
                font-family: Arial, Helvetica, sans-serif;
            }

            th {
                padding-top: 12px;
                padding-bottom: 12px;
                text-align: center;
                background-color: #4CAF50;
                color: white;
            }

            tr {
                text-align: right;
                -moz-transition: all .2s ease-in;
                -o-transition: all .2s ease-in;
                -webkit-transition: all .2s ease-in;
                transition: all .2s ease-in;
                background: white; 
                padding: 20px;
            }

            .disabled {
                color: lightgrey;
            }

            .saving {
                background: yellow;
            }

            .saved {
                background: lightgreen;
            }

            .error {
                background: red;
            }

            .sort:after {
                content: ' ↓';
            }
        `;
    }
}

export default TableList;
 

Комментарии:

1. Вам не нужно создавать свои собственные методы get / set для data . Это сделано для вас, поскольку data это свойство. Вам нужно искать изменения data в updated(changedProperties) методе LitElement.

2. @Thad Но я хочу упорядочить список, как только он будет установлен, поэтому мне нужно его перезаписать.

3. Возможно, это поможет вам с сортировкой таблицы по столбцам со значками в lit-элементах jsabarinath.wordpress.com/2021/03/12 /…

Ответ №1:

  1. Если вы используете массив с идентификатором в шаблоне, используйте функцию повтора lit-html

    импортируйте { repeat } из «lit-html/directives/repeat»;

  2. Для стилизации не добавляйте классы в DOM вручную. Используйте classMap из lit-html

    импортируйте { classMap } из «lit-html/directives/class-map»;

Я исправил вашу проблему с флажком, пожалуйста, перейдите по этой ссылке.

Для получения дополнительной информации о lit-html, пожалуйста, обратитесь к их документации.