#html #angular
#HTML #angular
Вопрос:
У меня есть проблема, которая связана с моим *ngIf
. У меня есть две кнопки, отображающие разные данные в одной таблице. Я фильтрую массив объектов. Проблема в том, что если я нажму на одну из этих кнопок, например «Dog», отобразятся правильные данные, но после того, как я нажму на «cat», столбцы будут пустыми. Кто — нибудь знает , что я делаю не так?
animal.ts
cat: boolean;
dog: boolean;
animals: Animal[] = [
{type: 'cat', name: 'snoopy', color: 'white'},
{type: 'dog', name: 'spooch', color: 'black'}
];
chooseCat() {
this.cat = true;
this.dog = false;
this.animals = this.animals.filter(d => {
return d.type === 'cat'
});
}
chooseDog() {
this.cat = false;
this.dog = true;
this.animals = this.animals.filter(d => {
return d.type === 'dog'
});
}
animal.html
<div class="col-xs-12" class="icon" (click)="chooseCat()">
<img src="../assets/img/cat.png" class="icon;">
cat
</div>
<div class="col-xs-12" class="icon" (click)="chooseDog()">
<img src="../assets/img/dog.png" class="icon;">
dog
</div>
<table *ngIf="cat || dog">
<tr>
<td>name</td>
<td>color</td>
</tr>
<tr *ngFor="let a of animals">
<td>{{a.name}}</td>
<td>{{a.color}}</td>
</tr>
</table>
Комментарии:
1. При выборе dog отфильтрованные данные содержат только dogs, поэтому в
animals
массиве нет cat. Кроме того, вам нужно сделать свойanimals
доступным только для чтения, и вы должны использовать временную переменную. Или вы можете просто использоватьpipe
для фильтрации.2. Ваша фильтрация путем проверки
name
свойства, но вы хотели проверитьtype
свойство.3. У вас один тип и одна логическая ошибка. Поскольку атрибут фильтра Typio неверен при входе, вы не должны фильтровать один и тот же массив снова и снова, ваши основные данные должны быть одинаковыми, вам нужно создать массив фильтров из основного массива. Одним решением является второй массив, другим — канал. В ответе я подробно описал оба примера, вы можете проверить это @yorozuya
Ответ №1:
ваше условие фильтра неверно измените тип и создайте еще один массив и подтвердите его в html
this.animals2 = this.animals.filter(d => {
return d.type == 'cat'
});
в html как
<tr *ngFor="let a of animals2">
<td>{{a.name}}</td>
<td>{{a.color}}</td>
</tr>
или другое решение — пользовательский канал
добавить пользовательский канал
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(value: any[], args: string): any {
console.log(value)
return value.filter(x=>x.type==args);
}
}
создать typee
в качестве параметра в компоненте
typee:string;
в html изменить typee
<div class="col-xs-12" class="icon" (click)="typee='cat'">
<img src="../assets/img/cat.png" class="icon;">
cat
</div>
<div class="col-xs-12" class="icon" (click)="typee='dog'">
<img src="../assets/img/dog.png" class="icon;">
dog
</div>
затем назначьте пользовательский канал таблице
<tr *ngFor="let a of animals | filter : typee">
<td>{{a.name}}</td>
<td>{{a.color}}</td>
</tr>
Ответ №2:
При первом нажатии на «Cats» и фильтрации вы исключаете всех собак из массива «this.animals». Когда вы затем нажимаете на ‘Dogs’, вы фильтруете всех cats из того же массива, таким образом, полностью очищая его. Если вы хотите отобразить всех собак или кошек, вам лучше выполнить глубокую копию вашего исходного массива, а не фильтровать его.
Комментарии:
1. Это в основном правильно, хотя я не думаю, что здесь желательно глубокое копирование. Также это не ответ
Ответ №3:
Вы фильтруете по «имени» в своих методах. Это должно быть ‘type’.
Попробуйте это:
chooseCat() {
this.cat = true;
this.dog = false;
this.animals = this.animals.filter(d => {
return d.type === 'cat'
});
}
Комментарии:
1. Спасибо, я изменил условие, но оно все еще не работает. Я могу отобразить один список, но если я нажму на другую кнопку, чтобы отобразить второй список, он вернет пустой