#angular #typescript
#angular #typescript
Вопрос:
У меня есть массив таких объектов
[
{"desc":"a", "menu": 1},{"desc":"b", "menu": 2},{"desc":"c", "menu": 1},
{"desc":"d", "menu": 3},{"desc":"e", "menu": 3},{"desc":"f", "menu": 2},
{"desc":"g", "menu": 1},{"desc":"g", "menu": 1},{"desc":"g", "menu": 4},
{"desc":"g", "menu": 4},{"desc":"g", "menu": 4}
]
Извлекается из API.
Теперь я бы показал, что объекты с *ngFor
помощью a, сгруппировав их по «меню» и добавив к нему метку следующим образом
Меню 1
{все объекты меню 1}
Меню 2
{все объекты меню 2}
Меню 3
{все объекты меню 3}
Я бы сделал что-то подобное в *ngFor
*ngFor="let object of objects; let menu = 0"
if menu !== object.menu
menu === object.menu
WRITE LABEL
Но как я мог бы реализовать это в реальном прецедентном коде?
Ответ №1:
Я думаю, мы должны сгруппировать его перед использованием *ngFor
вот решение
function groupBy(array, fn) {
return array.reduce(
(acc, current) => {
const groupName = typeof fn === 'string' ? current[fn] : fn(current);
(acc[groupName] = acc[groupName] || []).push(current);
return acc;
},
{}
);
}
function toArray(obj) {
return Object.keys(obj).map(k => obj[k]);
}
const data = [
{"desc":"a", "menu": 1},{"desc":"b", "menu": 2},{"desc":"c", "menu": 1},
{"desc":"d", "menu": 3},{"desc":"e", "menu": 3},{"desc":"f", "menu": 2},
{"desc":"g", "menu": 1},{"desc":"g", "menu": 1},{"desc":"g", "menu": 4},
{"desc":"g", "menu": 4},{"desc":"g", "menu": 4}
]
const groupMenu = groupBy(data, (item) => item.menu);
Затем в шаблоне
<group *ngFor="let group of groupMenu">
<menu *ngFor="let menu of group">
<label>{{menu.desc}}</label>
</menu>
</group>
Ответ №2:
Вы можете использовать что-то вроде
ngOnInit(){
var groups = new Set(this.array.map(item => item.menu))
this.result = [];
groups.forEach(g =>
this.result.push({
menu: g,
values: this.array.filter(i => i.menu === g)
}
))
}
и в HTML отображать данные
<p>
Start editing to see some magic happen :)
</p>
<div *ngFor="let item of result" border="1">
<table>
<tr>
<th>Desc</th>
<th>Menu</th>
</tr>
<ng-container>
<tr>
<td colspan="2">{{item.menu}}</td>
</tr>
<tr *ngFor="let value of item.values">
<td>{{value.desc}}</td>
</tr>
</ng-container>
</table>
<div>
Пожалуйста, проверьте stackblitz, который я сделал.
https://stackblitz.com/edit/angular-4ekz4n
Счастливого кодирования 🙂
Ответ №3:
Напишите оператор импорта в компоненте angular
import { of } from 'rxjs';
import { groupBy, mergeMap } from 'rxjs/operators';
Затем в ngOnInit()
ngOnInit():void{
on(
{id: 1, name: 'JavaScript'},
{id: 2, name: 'Parcel'},
{id: 2, name: 'webpack'},
{id: 1, name: 'TypeScript'},
{id: 3, name: 'TSLint'}
).pipe(groupBy(a=>a.id)),
mergeMap((group$) => group$.pipe(reduce((acc, cur) => [...acc, cur], []))),
)
.subscribe(p => console.log(p));
// Вывод
[ { id: 1, name: 'JavaScript'},
{ id: 1, name: 'TypeScript'} ]
[ { id: 2, name: 'Parcel'},
{ id: 2, name: 'webpack'} ]
[ { id: 3, name: 'TSLint'} ]
Для получения дополнительной информации обратитесь к RxJS
Ответ №4:
Сначала вам нужно обновить структуру текущего массива до структуры, как показано ниже:
[
{
menu: 1,
desc: ["a", "b"]
},
{
menu: 2,
desc: ["a1", "b1", "c1", "d1"]
}
]
Вы можете обновить, выполнив итерацию текущего массива в файле ts компонента и упорядочить, как показано в примере выше.
После этого вы можете использовать этот обновленный массив в *ngFor в html для отображения данных.