Применение Angular2 Pipe после получения данных

У меня есть Object это используется для управления данными, полученными от серверной части. Инициируется со всеми полями как display: falseи если я получу это конкретное поле с сервера, я в конечном итоге изменит его на true,

Группа фильтров (начальная):

export let filterGroups: any = {
    genericFilters: {
        iboId: {
            'display': false,
            'template': ''
        },
        iboCode: {
            'display': false,
            'template': 'text/iboCode'
        },
        iboName: {
            'display': false,
            'template': 'text_input_iboName'
        },
        iboSurname: {
            'display': false,
            'template': 'text_input_iboSurname'
        },
        iboRank: {
            'display': false,
            'template': 'select/multi_iboRank',
        },
        iboEmail: {
            'display': false,
            'template': 'text_input_iboEmail'
        },
        iboNewsletter: {
            'display': false,
            'template': 'select/simple_iboNewsletter',
        },
    },
    orderFilters: {
        iboTotalOrders: {
            'display': false,
            'template': 'compound/iboTotalOrders',
        }
    },
    peFilters: {
        iboTotalPE: {
            'display': false,
            'template': 'checkbox/iboTotalPE',
        }
    },
};

В моем шаблоне я хочу иметь как можно больше div как группы фильтров. В этом случае у нас есть 3 группы фильтров: genericFilters, orderFilters а также peFilters,

это Object будет изменен, как только я получу данные с сервера (который я называю в моем constructor).

И так, мой filterGroups будет выглядеть после получения данных от моего асинхронного вызова.

filterGroups (после асинхронного вызова):

export let filterGroups: any = {
    genericFilters: {
        iboId: {
            'display': true,
            'template': ''
        },
        iboCode: {
            'display': true,
            'template': 'text/iboCode'
        },
        iboName: {
            'display': true,
            'template': 'text_input_iboName'
        },
        iboSurname: {
            'display': true,
            'template': 'text_input_iboSurname'
        },
        iboRank: {
            'display': false,
            'template': 'select/multi_iboRank',
        },
        iboEmail: {
            'display': true,
            'template': 'text_input_iboEmail'
        },
        iboNewsletter: {
            'display': false,
            'template': 'select/simple_iboNewsletter',
        },
    },
    orderFilters: {
        iboTotalOrders: {
            'display': true,
            'template': 'compound/iboTotalOrders',
        }
    },
    peFilters: {
        iboTotalPE: {
            'display': false,
            'template': 'checkbox/iboTotalPE',
        }
    },
};

Теперь в моем шаблоне у меня есть это:

Шаблон (HTML):

<div *ngFor="let group of filterGroups | keysCheckDisplay">
    <div>
        <h4>{{group.key}}</h4>
    </div>
</div>

И, конечно же, вот мой @Pipe,

@Pipe:

import { PipeTransform, Pipe } from '@angular/core';
import { isNullOrUndefined } from 'util';

@Pipe({name: 'keysCheckDisplay'})
export class KeysCheckDisplayPipe implements PipeTransform {
    transform(value, args: string[]): any {
        let keys = [];
        for (let key in value) {
            if (!isNullOrUndefined(value[key])) {
                let display = false;
                for (let keyChild in value[key]) {
                    if (!isNullOrUndefined(value[key][keyChild]) && value[key][keyChild]['display'] === true) {
                        display = true;
                        break;
                    }
                }
                if (display === true) {
                    keys.push({key: key, value: value[key]});
                }
            }
        }
        return keys;
    }
}

В этом @Pipe как видите, я делаю несколько вещей:

  • Перебрать filterGroups объект
  • Проверьте для каждой группы в объекте, если существует ребенок с display: true,

Функциональность:

я хочу этот @Pipe перебрать мой Objectи вернуть мне "группы фильтров", которые имеют по крайней мере 1 элемент сdisplay: true,

Проблема:

@Pipe получает первую версию filterGroups объект, и игнорирует тот факт, что объект изменяется, как только я получаю данные с сервера.

@Pipe работает нормально, если я изменяю начальные значения filterGroups объект.

Что я пробовал:

  • Исследование, исследование, исследование
  • Я изменил @Pipe чтобы излечиться, но я ненавижу это решение из-за ужасной производительности, а также оно вошло в бесконечный цикл.
  • Я также попробовал этот подход: *ngFor="let group of filterGroups | async | keysCheckDisplay", Но это бросило следующую ошибку:

Ошибка: InvalidPipeArgument: '[объект объекта]' для канала 'AsyncPipe'

Возможные решения?

  • Изменить @Pipe?

  • Изменить начальный object?

  • Создать второй @Pipe перебрать результат первой трубы?

Я надеюсь, что это было подробно и ясно, если нет, пожалуйста, не стесняйтесь комментировать, прося более подробную информацию, и я с удовольствием обновлю сообщение.

Спасибо заранее!

1 ответ

Решение

Чистый канал вызывается только при изменении данных. Это означает, что когда "данные" являются новым экземпляром объекта. Если изменяется только содержимое объекта, то обнаружение угловых изменений не распознает его как изменение и не вызовет канал.

Возможные подходы

  • сделать трубу нечистой: обычно это бремя для производительности
  • скопируйте объект как:
var tmp = this.data; this.data = {}; Object.assign(this.data, tmp);
  • добавить дополнительный параметр в канал и обновить значение параметра
*ngFor="let item of data | myPipe:counter"
// updated `data`
// this.counter++;
Другие вопросы по тегам