обновление, это решение работает, только если два компонента не отображаются одновременно
в компоненте представления подписки, вы подписываетесь на метод инициализации только в службе
поэтому, если в методе onlyCRNAFilterForSubject в службе произошли некоторые изменения, вы не будете знать об этом
мы можем добавить логическое свойство к службе, чтобы указать, находимся ли мы в режиме фильтрации или нет, и установите это свойство в компоненте фильтра подписки, когда мы вызываем службу
, поэтому вместо постоянной подписки на метод инициализации мы можем подписаться на тест $ observable, если мы находимся в режиме фильтрации
поэтому в сервисе нам нужно определить новое логическое свойство, подобное этому
isFilteringMode: Boolean = false; // set it initailly to false, to get all the data once the component is loaded at the first time
, а в компоненте фильтра подписки нам нужно установить для этого свойства значение true после выбора какой-либо CRNA
filterOnCRNAOnly() {
console.log(this.selectedCRNA);
this.subscriptionService.isFilteringMode = true; // enable the filtering mode
this.subscriptionService.onlyCRNAFilterForSubject(this.selectedCRNA);
this.selectedCRNALabel = this.selectedCRNA;
}
в компоненте представления подписки, в режиме инициализации мы подпишемся на сервисную функцию, которая возвращает весь массив, и когда выбран некоторый CRNA (режим фильтрации), мы можем подписаться на тест $ observable,
, поэтому в компоненте представления подписки это будет что-то вроде
ngOnInit() {
this.tableHeaders = [
{ field: 'status', header: 'Status' },
{ field: 'region', header: 'Region' },
{ field: 'provider', header: 'Fournisseur' },
{ field: 'host', header: 'Bus' },
{ field: 'consumer', header: 'Consommateur' },
{ field: 'alias', header: 'Alias' },
{ field: 'filters', header: 'Abonnement' },
{ field: '', header: 'Actions' },
{ field: '', header: 'Selections' }
];
this.copiedSubscription = new SubscriptionModel();
this.loadAll();
}
/**
* Method to load all subscriptions
*/
loadAll() {
if (this.subscriptionService.isFilteringMode) {
// we are in the filtering mode
// here we will subscribe to test$ observable to get the filtered data
this.subscriptionService.test$.subscribe((res: any) => {
this.subscriptions = res;
this.isLoadingResults = false;
});
} else {
// we are not in the filtering mode
// so get all the data
this.subscriptionService.initializeSubscriptions().subscribe((res: any) => {
this.subscriptions = res;
this.isLoadingResults = false;
})
}
}
Обновление, вот похожий мини-проект, подобный вашему
здесь у нас есть компонент списка, который перечисляет некоторых пользователей, и компонент фильтра, который используется для выбора некоторого статуса для фильтрации кандидатов в компоненте списка
мы можем использовать BehaviorSubject
для переноса выбранного состояния из компонента фильтра в компонент списка
BehaviorSubject
очень полезно в таком случае, так как содержит начальное значение, и нам не нужно ждать подписки на него, чтобы получить значение
, здесь вы можете найти разницу Subject vs BehaviorSubject
вот файлы
app.component. html
<div class="row container">
<div class=" row col-md-12">
<div id="subscription-filter">
<app-candidates-filter></app-candidates-filter>
</div>
</div>
<div class="row col-md-12" style="margin-top: 30px;">
<div id="subscription-view">
<app-candidates-list></app-candidates-list>
</div>
</div>
</div>
sources-list.component.ts
import { Component, OnInit } from '@angular/core';
import { SharedService } from '../shared.service';
import { User } from '../user.model';
@Component({
selector: 'app-candidates-list',
templateUrl: './candidates-list.component.html',
styleUrls: ['./candidates-list.component.css']
})
export class CandidatesListComponent implements OnInit {
originalCandidatesList: User[];
candidatesList: User[];
constructor(private sharedService: SharedService) { }
ngOnInit() {
console.log('in candidates list component');
this.sharedService.selectedStatusObs.subscribe((selectedStatus: number) => { // subscribe to the selected status first
console.log(selectedStatus);
if (!selectedStatus) {
// no status has been selected
console.log('no status selected');
this.sharedService.getAllCandidatesV2().subscribe((res: User[]) => { // get all the users from the service
// console.log(res);
// console.log(typeof(res));
this.originalCandidatesList = res;
this.candidatesList = res;
});
} else {
// some status has been selected
console.log('some status selected >>> ', this.sharedService.statuses);
const selectedStatusObj = this.sharedService.statuses.find(item => item.code === +selectedStatus);
console.log('selectedStatusObj >>> ', selectedStatusObj);
// just getting the selected status candidates
this.candidatesList = this.originalCandidatesList.filter(item => item.status === selectedStatusObj.name);
}
});
}
}
sources-list.component. html
<table class="table table-responsive table-hover">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email Address</th>
<th>Age</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let can of candidatesList'>
<td>{{ can.firstName }}</td>
<td>{{ can.lastName }}</td>
<td>{{ can.emailAddress }}</td>
<td>{{ can.age }} years</td>
<td>{{ can.status }}</td>
</tr>
</tbody>
</table>
кандидатов-filter.compone nt.ts
import { Component, OnInit } from '@angular/core';
import { SharedService } from '../shared.service';
@Component({
selector: 'app-candidates-filter',
templateUrl: './candidates-filter.component.html',
styleUrls: ['./candidates-filter.component.css']
})
export class CandidatesFilterComponent implements OnInit {
statuses = [];
selectedStatus: number;
constructor(private sharedService: SharedService) { }
ngOnInit() {
console.log('in candidates filter component');
this.statuses = this.sharedService.statuses;
}
filterCandidates() {
console.log(this.selectedStatus);
this.sharedService.selectedStatusObs.next(this.selectedStatus);
};
resetFilters() {
// emil null to the selectedStatus Observable
this.sharedService.selectedStatusObs.next(null);
}
}
sources-filter.component. html
<div class="row col-xs-12">
<div class="row col-xs-8">
<label class="col-xs-3">Select Status </label>
<select class="col-xs-9 form-control" [(ngModel)]="selectedStatus">
<option *ngFor="let status of statuses" [value]="status.code">
{{ status.name }}
</option>
</select>
</div>
<div class="col-xs-4" style="margin-top: 25px;">
<button type="submit" class="btn btn-primary" (click)="filterCandidates()">Search</button>
<button type="submit" class="btn btn-default" (click)="resetFilters()">Reset</button>
</div>
</div>
shared.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, of } from 'rxjs';
import { User } from './user.model';
@Injectable({ providedIn: 'root' })
export class SharedService {
selectedStatusObs = new BehaviorSubject<number>(null); // this is the observable to watch the selected status in the filter component
candidates: User[] = [ // a list of users
{
firstName: 'Thierry',
lastName: 'Henry',
emailAddress: 'henry@test.com',
age: 1,
status: 'Active'
},
{
firstName: 'Alexis',
lastName: 'Sanchez',
emailAddress: 'sanchez@test.com',
age: 28,
status: 'Idle'
},
{
firstName: 'Denis',
lastName: 'Bergkamp',
emailAddress: 'Bbrgkamp@test.com',
age: 29,
status: 'Active'
},
{
firstName: 'Jerman',
lastName: 'Defoe',
emailAddress: 'defoe@test.com',
age: 22,
status: 'Active'
},
{
firstName: 'Kun',
lastName: 'Aguero',
emailAddress: 'aguero@test.com',
age: 25,
status: 'Offline'
},
];
statuses = [
{
code: 1,
name: 'Active'
},
{
code: 2,
name: 'Offline'
},
{
code: 3,
name: 'Idle'
}
]
getAllCandidatesV2() {
return of(this.candidates); // trying to mock the HTTP request via this 'of' observable
}
}
user.model.ts
export class User {
constructor(
public firstName: String,
public lastName: String,
public emailAddress: String,
public age: Number,
public status: String
) { }
}