Применение 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++;