Генерация повторяющихся идентификаторов в ngForOf — Angular

Я использую ngForOf для перечисления дат, каждая дата представлена ​​свойством id, которое на самом деле является ее индексом + 1. Все даты представлены в виде объекта в массиве. Кроме того, каждая дата является экземпляром компонента.

Дело в том, что ngForOf заключается в том, что всякий раз, когда я удаляю дату из списка, вся DOM обновляется, и идентификаторы назначаются снова и снова.

<app-date *ngFor="let date of dates | callback: filterDates; index as i" (delete)="del(i)"></app-date>

Проблема

Теперь, когда я говорю «удалить», я не объединяю/удаляю дату из массива, а устанавливаю для свойства action даты значение "deleted". Это сделано для того, чтобы мне не приходилось делать HTTP-запросы для каждой даты, чтобы удалить ее из базы данных.

Как только action становится "deleted", дата не отображается в DOM, но все еще присутствует в массиве. Итак, в следующий раз, когда DOM обновится, он переназначит идентификаторы, и теперь у меня будут дубликаты идентификаторов в массиве. Это имеет много последствий, самое большое из которых заключается в том, что я не могу удалить даты с одним и тем же идентификатором.

Я также пытался изменить идентификатор даты для каждого события удаления, но это также портит массив.

Важно

Я знаю о trackBy, но я не понимаю, как я могу применить его для решения этой проблемы, и не вижу проблемы в Интернете, связанной с этим.

Спасибо.


person Hasham Ali    schedule 11.08.2020    source источник
comment
Вы должны просто удалить дату вашего массива дат, и вы не делаете http-запрос. Список обновится, дубликатов больше не будет. Все еще не понимаете, как ваши даты могут иметь один и тот же уникальный идентификатор, если вы получаете их из своей базы данных. Если вам когда-нибудь понадобится удалить даты в базе данных, вам просто нужно будет наконец использовать свой массив.   -  person Leccho    schedule 11.08.2020
comment
Если я удалю дату и отправлю ее на сервер, он не будет знать, какая конкретно дата была удалена, какая изменена, а какая добавлена. Если я буду следовать этому подходу, мне сначала нужно будет удалить все даты, принадлежащие этому конкретному пользователю, и снова добавить их в измененной форме. - Лекчо   -  person Hasham Ali    schedule 11.08.2020
comment
Любая демо-версия stackblitz может помочь нам решить проблему.   -  person Kamran Khatti    schedule 11.08.2020


Ответы (1)


Я смог решить проблему.

  • Фон

По сути, есть два массива: один — это массив dates, через который я прохожу для отображения дат, другой массив — тот, который содержит элементы DOM, представляющие каждую дату, отображаемую на экране. Angular не заботится о том, что id или индекс имеет дата в массиве dates, присутствующем в файле component.ts. По умолчанию он отслеживает каждый элемент в цикле ngFor по индексу в массиве DOM. Этот массив постоянно изменяется для каждой операции добавления/удаления.

Ошибка, которую я сделал, заключалась в том, что я использовал индекс массива DOM в качестве id даты. Теперь из-за удаления какой-либо даты массив DOM обновлялся, и, поскольку я никогда не удалял и не объединял дату из массива, в массиве всегда было несколько повторяющихся id.

  • Решение

Должна быть отдельная функция генерации идентификатора или, может быть, просто свойство числового типа, которое продолжает увеличиваться при каждой операции pushDate(). Это в некоторой степени решит проблему id дублирования. Хотя Angular по-прежнему не заботится о id и может идентифицировать каждый элемент даты только по его индексу в массиве DOM, поэтому для удаления конкретной даты вам нужен ее индекс в массиве DOM.

<app-date *ngFor="let date of dates | callback: filterDates; index as i" [id]="dateID" (delete)="del(i, $event)"></app-date>

Теперь (delete) вернет строку, показывающую дату, например: 2020-8-15. Эта дата вместе со свойством action этой конкретной даты будет определять дату, которая будет установлена ​​на deleted. Вот как я это делаю:

getArrayIndex = (index: number, date: string): number => {
    for (let i = 0; i < this.dates.length; i++) {
        if(i == index && date == this.dates[i]['date']) {
            if(this.dates[i]['action'] == 'deleted') {
                return this.getArrayIndex(i + 1, date);
            }
            else {
                return i;
            }
        }
        else if(i == index && date != this.dates[i]['date']) {
            return this.getArrayIndex(i + 1, date);
        }
        else if(i != index) {
            continue;
        }
        else {
            return i;
        }
    }
}

del = (num: number, event: string) => {
    let i = this.getArrayIndex(num, event);
    this.dates[i]['action'] = 'deleted';
}

Функция del сначала находит правильный индекс удаляемой даты в массиве от dates до getArrayIndex(). Как только date найдено, свойство action этого конкретного объекта даты устанавливается на "deleted".

person Hasham Ali    schedule 15.08.2020