/ / Jak wybrać wszystkie przefiltrowane pola wyboru wewnątrz ngFor w Angular 2? - kątowe, ngfor

Jak wybrać wszystkie przefiltrowane pola wyboru wewnątrz ngFor w Angular 2? - kątowe, ngfor

Mam element Angular 2, który ładuje i pokazuje listę pól wyboru dla użytkownika wewnątrz *ngFor, lista może być również filtrowana na podstawie klucza. Muszę wybrać wszystkie przefiltrowane elementy i dodać je do tablicy. Mogę sprawdzić wszystkie pola wyboru, ale problem występuje, gdy zmieniam checked problematycznie change zdarzenie nie uruchamia się, jakikolwiek pomysł, jak to naprawić?

szablon:

<div class="form-group">
<input type="text" class="form-control" id="stringKeyFilter" placeholder="Key Filter"
[(ngModel)]="keyFilter">
</div>

<table class="table table-striped table-hover">
<thead>
<tr>
<th>Id</th>
<th style="width: 150px;">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let device of devices| stringFilter: keyFilter">
<td>
{{device.$key}}
</td>
<td>
<div class="checkbox">
<label> <input type="checkbox"
[checked]="selectAll || selectedDevices.indexOf(device.$key) > -1"
(change)="updateSelectedDevices(device.$key, $event)" > View</label>
</div>
</td>
</tr>
</tbody>
</table>

<div class="btn-group pull-right">
<button type="button" class="btn btn-primary" (click)="selectAllDevices()">Select All</button>
<button type="button" class="btn btn-default" (click)="deselectAllDevices()">Deselect All
</button>
</div>

Składnik:

@Component({
moduleId: module.id,
selector: "device-list",
template: template
})
export class DeviceListComponent implements OnInit {
devicesObservable: FirebaseListObservable<Device[]>;
devices: Device[] = [];
isLoading: boolean = true;
selectedDevices: string[] = [];
selectAll: boolean = false;
allCtrl: any;

keyFilter: string = "";

constructor(private af: AngularFire) {

}

ngOnInit(): void {


this.devicesObservable = this.af.database.list("/online", {
query: {
orderByKey: true,
}
});
this.devicesObservable.subscribe((devicesData)=> {
this.devices = devicesData;
this.isLoading = false
});
}

updateSelectedDevices(deviceId: string, event): void {
if (event.target.checked) {
this.selectedDevices.push(deviceId);
}
else {
_.pull(this.selectedDevices, deviceId);
}
}


loadingDeviceDetail(loading: boolean): void {
this.isLoading = loading;
}

selectAllDevices(): void {
this.selectAll = true;
}

deselectAllDevices(): void {
this.selectAll = false;
this.selectedDevices = [];
}

}

wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj

Odpowiedzi:

6 dla odpowiedzi № 1

Aktualizacja

Zaktualizowany kod przykładowy i plunker do demonstracji zaznacz / odznacz wszystkie pola wyboru dla filtrowanej listy.


Zgodnie z moim rozumieniem, zachowanie filtra zmieniło się z Angular1 na Angular2.

W Angular1, gdy parametr danych lub filtra zostanie zmodyfikowany, DOM (strona internetowa) zostanie ponownie obliczony. (Być może się myliłem, zbyt dawno temu: P)

W Angular2, w skrócie, modyfikowanie danych (tablica) nie spowoduje wyliczenia filtra, więc nie ma nowych wyników, żadnych aktualizacji do DOM.

Długie i oficjalne wyjaśnienie jest tutaj: Angular2 Pipes - ts. Jeśli nalegasz na używanie potoku (filtra) w szablonie, powinieneś poznać zanieczyszczona rura sekcja w dokumencie.

Innym rozwiązaniem jest nie używać filtra *ngFor. Zamiast tego utwórz przefiltrowaną listę.

Plunker

http://plnkr.co/edit/pEpaj0?p=preview

Przykładowy kod

app.component.ts

import {Component} from "@angular/core";
import {bootstrap} from "@angular/platform-browser-dynamic";

@Component({
selector: "material-app",
templateUrl: "app.component.html"
})
export class AppComponent {

title="How to select all filtered checkboxes inside ngFor in Angular 2?";
url="http://stackoverflow.com/questions/39703103/";

device = [
{"name":"abc","checked":false},
{"name":"abcd","checked":false},
{"name":"abcde","checked":false},
{"name":"abc123","checked":false},
{"name":"abc1234","checked":false}];

deviceFilter = "";

deviceFiltered = this.device.slice(0);

selectFiltered(){
this.deviceFiltered.forEach(i=>i.checked=true);
}

deSelectFiltered(){
this.deviceFiltered.forEach(i=>i.checked=false);
}

onFilterChange(){
if (this.deviceFilter.length > 0) {
this.deviceFiltered = this.device.filter(i => i.name.indexOf(this.deviceFilter) > -1);
console.log(this.deviceFiltered);
} else {
this.deviceFiltered = this.device.slice(0);
}
}
}

app.component.html

<h2><a [href]="titleUrl">{{title}}</a></h2>

<div>
Filter
<input [(ngModel)]="deviceFilter" (ngModelChange)="onFilterChange()">
</div>

<div>
List:
<ul>
<li *ngFor="let i of device">
<input type="checkbox" [(ngModel)]="i.checked">{{i.name}}
</li>
</ul>
</div>

<div>
Filtered List:
<ul>
<li *ngFor="let i of deviceFiltered">
<input type="checkbox" [(ngModel)]="i.checked">{{i.name}}
</li>
</ul>
<button (click)="selectFiltered()">Select Filtered</button>
<button (click)="deSelectFiltered()">Deselect Filtered</button>
</div>

3 dla odpowiedzi № 2

Gdy próbujesz wybrać wszystkie urządzenia, swoją głównąlista, nie jest aktualizowana, nic się nie zmieniło i kąt nie wykrywa na niej zmian. (Istnieje zaktualizowana flaga, ale lista jest taka sama) Masz dwie opcje:

  1. Umieść flagę na każdym zaznaczonym elemencie na liście.
  2. Uruchom wyzwalanie ręczne za pomocą ApplicationRef.tick () https://angular.io/docs/ts/latest/api/core/index/ApplicationRef-class.html#!#tick-anchor

1 dla odpowiedzi nr 3

Uwaga: Twój kod może się różnić, ponieważ wprowadziłem pewne zmiany, aby uzyskać działającą aplikację. Pobierz powiązaną część z fragmentów kodu i zastosuj.

Oto działający kod dla twojego pytania.

Poniżej znajdują się zmiany, które należy wprowadzić w kodzie.

<input type="checkbox"  [checked]="selectedDevices.indexOf(device.$key) > -1"
(change)="updateSelectedDevices(device.$key, $event)" >

Zmień wybraną funkcję jako następującą.

selectAllDevices(): void {
this.selectedDevices = this.strFilter(this.devices, this.keyFilter).map(dev=>dev.$key);
}

Uwaga: this.strFilter jest funkcją filtra w klasie / funkcji komponentu. To zależy od klasy filtru. Mam utworzyć filtr / potoku w ten sposób.

//stringfilter.pipe.ts

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({name: "stringFilter"})
export class StringFilter implements PipeTransform {
transform(value: Array<any>, filterKey: string): Array<any> {
return (
filterKey ? value.
filter(el => (el.name).toLowerCase().includes(filterKey))
: value
);
}
}

W klasie komponentów podobało mi się // klasa komponentu

import {StringFilter} from "./filter-file"

I

ngOnInit(): void {

this.strFilter = new StringFilter().transform;
//this.devices = [];
this.isLoading = false;

}

Przetestowałem następujący kod. Mam nadzieję, że to rozwiązuje twój problem.