First of all, I am not a Front-end developer. I'm more specialized in back-end development. But, I have to do an app with Angular (I chose Angular 8). In previous work, I used Angular. But it's my first time I have to create an Angular app from scratch.
I have to read, add, modify and delete objects (called subscriptions). All this is fine.
Except when I wish to filter with a form...
To be more in the code, my page HTML is constructed that way :
subscription.component.html
<div id="subscription-filter">
<app-subscription-filter></app-subscription-filter>
</div>
<div id="subscription-view">
<app-subscription-view></app-subscription-view>
</div>
Where I have problems are with app-subscription-filter and app-subscription-view
subscription-filter part :
subscription-filter.component.html
<div class="row col-12">
<div class="row col-11">
<label class="col-1" for="selectCRNA">{{filterLabel}} </label>
<select class="col-11 form-control" [(ngModel)]="selectedCRNA">
<option *ngFor="let crna of filterSelection">
{{crna.name}}
</option>
</select>
</div>
<div class="col-1">
<button type="submit" class="btn"><i class="fas fa-search fa-lg" (click)="filterOnCRNAOnly()"></i></button>
</div>
</div>
...
subscription-filter.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { Observable } from 'rxjs';
import { SubscriptionService } from '../../shared/service/subscription.service';
@Component({
selector: 'app-subscription-filter',
templateUrl: './subscription-filter.component.html',
styleUrls: ['./subscription-filter.component.css']
})
export class SubscriptionFilterComponent implements OnInit {
filterLabel: string;
filterSelection: any[];
selectedCRNA: string;
selectedCRNALabel: string;
addSubscriptionForm : FormGroup;
@ViewChild('closebutton', {static: false}) closebutton;
constructor (protected subscriptionService: SubscriptionService) {
}
ngOnInit() {
this.filterLabel = "Filtrer sur le tableau de résultat :";
this.filterSelection = [
{ name: "Tous CRNA", value: "All" },
{ name: "CRNA NORD", value: "CRNA NORD" },
{ name: "CRNA SUD", value: "CRNA SUD" },
{ name: "CRNA EST", value: "CRNA EST" },
{ name: "CRNA OUEST", value: "CRNA OUEST" },
{ name: "CRNA SUD-OUEST", value: "CRNA SUD-OUEST" }
];
}
/**
* Method to filter on CRNA selected
*/
filterOnCRNAOnly() {
console.log(this.selectedCRNA);
this.subscriptionService.onlyCRNAFilterForSubject(this.selectedCRNA);
this.selectedCRNALabel = this.selectedCRNA;
}
}
...
subscription-view part :
subscription-view.html
<table class="table table-responsive table-hover" *ngIf="!!subscriptions || isLoadingResults">
<thead>
<tr>
<th *ngFor='let col of tableHeaders'>
{{col.header}}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let sub of (subscriptions)'>
<td scope='row'>{{sub.status}}</td>
<td>{{sub.region}}</td>
<td>{{sub.provider}}</td>
<td>{{sub.host}}</td>
<td>{{sub.consumer}}</td>
<td>{{sub.alias}}</td>
<td>{{sub.filters}}</td>
<td>
<i class="fas fa-play mx-1" data-toggle="tooltip" title="Start subscription" (click)="startSubscription(sub, sub.id)"></i>
<i class="fas fa-times mx-1" data-toggle="tooltip" title="Stop subscription" (click)="stopSubscription(sub, sub.id)"></i>
<i class="fas fa-trash mx-1" data-toggle="tooltip" title="Delete subscription" (click)="deleteSubscription(sub.id)"></i>
</td>
<td></td>
</tr>
</tbody>
</table>
subscription-component.ts
import { Component, OnInit } from '@angular/core';
import { SubscriptionModel } from '../../shared/model/subscription.model';
import { SubscriptionService } from '../../shared/service/subscription.service';
@Component({
selector: 'app-subscription-view',
templateUrl: './subscription-view.component.html',
styleUrls: ['./subscription-view.component.less']
})
export class SubscriptionViewComponent implements OnInit {
subscriptions: SubscriptionModel[] = [];
tableHeaders: any[];
isLoadingResults = true;
copiedSubscription: SubscriptionModel;
constructor(protected subscriptionService: SubscriptionService) { }
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() {
this.subscriptionService.initializeSubscriptions().subscribe((res: any) => {
this.subscriptions = res;
this.isLoadingResults = false;
})
}
/**
* Method to start a subscription
* @param sub
* @param id
*/
startSubscription(sub: SubscriptionModel, id: string) {
if (sub.status !== "OK") {
this.subscriptionService.changeSubscriptionStatus(id, "ON");
}
}
/**
* Method to stop a subscription
* @param sub
* @param id
*/
stopSubscription(sub: SubscriptionModel, id: string) {
if (sub.status === "OK") {
this.subscriptionService.changeSubscriptionStatus(id, "Off");
}
}
/**
* Method to delete a subscription
* @param id
*/
deleteSubscription(id: string) {
this.subscriptionService.deleteSubscription(id);
}
}
I don't have (for the moment) any server call. All my datas are mocked with a JSON file. And the data which must be displayed is test$;
subscription.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpResponse } from '@angular/common/http';
import { Subject, Observable, of } from 'rxjs';
import { tap, filter, map, catchError } from 'rxjs/operators';
import { History } from '../model/history.model';
import { SubscriptionModel } from '../model/subscription.model';
import { Hosting } from '../model/hosting.model';
@Injectable({
providedIn: 'root'
})
export class SubscriptionService {
mockHostingUrl: string = 'assets/jsontests/hostmockdata.json';
mockSubscribeUrl: string = 'assets/jsontests/subscriptionsmockdata.json';
private test$: Subject<SubscriptionModel[]> = new Subject<SubscriptionModel[]>();
private subsTest: SubscriptionModel[] = [];
copiedSub: SubscriptionModel;
crnaSelected: string = "Tous CRNA";
constructor(private http: HttpClient) { }
private handleError<T>(operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
// TODO: send the error to remote logging infrastructure
console.error(error); // log to console instead
// Let the app keep running by returning an empty result.
return of(result as T);
};
}
/**
* Method to initialize subscriptions
*/
initializeSubscriptions() : Observable<SubscriptionModel[]> {
return this.http.get<SubscriptionModel[]>(this.mockSubscribeUrl).pipe(tap((subs => {
this.subsTest = subs;
this.test$.next(this.subsTest);
})));
}
/**
* Method for adding a new subscription
* @param sub
*/
addSubscription(sub: SubscriptionModel) {
this.subsTest.push(sub);
this.test$.next(this.subsTest);
}
/**
* Method for changing subscription's status
* @param id
* @param changeStatus
*/
changeSubscriptionStatus(id: string, changeStatus: string) {
this.subsTest.find(element => {
if (element.id === id) {
element.status = changeStatus;
}
});
this.test$.next(this.subsTest);
}
/**
* Method to delete a subscription
* @param id
*/
deleteSubscription(id: string) {
this.subsTest.splice(this.subsTest.findIndex(element => element.id === id), 1);
this.test$.next(this.subsTest);
}
/**
* Method where there is the problem. It must filter and sending
* @param crnaSelected
*/
onlyCRNAFilterForSubject(crnaSelected: string) {
console.log("dans onlyCRNAFilter");
this.crnaSelected = crnaSelected;
if (crnaSelected !== "Tous CRNA") {
/*
var temp = this.subsTest.filter(element => {
element.region.includes(crnaSelected)
});
*/
console.log(this.subsTest);
var temp: SubscriptionModel[] = [];
this.subsTest.filter(
element => {
console.log("---");
console.log(element);
if (element.region.includes(crnaSelected)) {
temp.push(element);
console.log("dedans!");
}
}
);
console.log("apres fonction");
console.log(temp);
this.test$.next(temp);
} else {
console.log(this.subsTest);
this.test$.next(this.subsTest);
}
}
}
When I try to filter my table, I do have the right datas, but my HTML doesn't refresh with the correct data
I must confess I don't know what to do anymore... So, a bit help will be grateful.
Thanks in advance.
(Sorry for my English, it's not my native language)