I'm trying to do an action after creating an event.
Create a control form that has been selected in form1 several p, and update a PSelected table.
I have two files, A.html and A.ts
A.html:
<mat-select placeholder="form1" [formControl]="product" (ngModelChange)="getP($event)" multiple> <mat-option *ngFor="let p of allProduct" [value]="p.pro_nom">{{p.pro_nom}}</mat-option>
</mat-select>
<mat-form-field *ngFor="let valeurControls of valeursControls">
<input matInput maxLength="255" type="text [placeholder]="valeurControls.valeur.n [formControl]="valeurControls.formControl">
</mat-form-field>
A.ts:
import { ChangeDetectorRef, Component, OnInit, ViewEncapsulation, Output, EventEmitter } from '#angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '#angular/forms';
import { filter, takeUntil } from 'rxjs/operators';
import { Product, Candy } from 'src/app/models';
import { Service } from 'src/app/services';
import { Listener } from 'selenium-webdriver';
#Component({
selector: 'ei',
templateUrl: './A.component.html',
styleUrls: ['./A.component.less'],
encapsulation: ViewEncapsulation.None
})
export class AComponent extends FormFieldsContainer implements OnInit {
#Output('change') inputChange = new EventEmitter();
//var
allProduct: Product[];
Candy: Candy;
// Form
actionFormGroup: FormGroup;
product: FormControl;
event: Listener[]
// P
valeursControls: { valeur: candy, formControl: FormControl }[] = [];
public pSelected: Array<any>;
// Constructor
constructor(private fb: FormBuilder) {
super();
this.Candy = this.Candy ? this.Candy : { name: null, type: null };
this.pSelected = [];
this.buildForm();
}
ngOnInit() {
this.Service.getProduct()
.pipe(takeUntil(this.unsubscribe))
.subscribe(p => {
this.allProduct = p;
});
}
getP(event?: Event[]) {
if (typeof event == 'undefined') {
this.pSelected = [];
} else {
this.pSelected = event;
}
console.log(this.pSelected)
return this.pSelected;
}
getFormGroup(): FormGroup {
return this.actionFormGroup;
}
onSubmitSuccess<Boolean>(result: Boolean) {
}
private buildForm() {
this.submitted = false;
this.p= this.fb.control('', Validators.required);
this.actionFormGroup = this.fb.group({
product: this.product
});
// my array does not update, it remains empty
this.pSelected .forEach(p => {
const VarFormControl = this.fb.control(null);
this.valeursControls.push({
valeur: { name: p, type: this.Candy.type },
formControl: VarFormControl
});
this.actionFormGroup.addControl(p, VarFormControl );
});
}
Actions() {
this.submitted = true;
}
}
in the function getP(), my table is updating, but when I use it in buildForm() it is empty yet it should have the same value
you are calling this.buildForm(); from the component constructor.
The value of pSelected will be the declared one: public pSelected: Array;
You should rebuild valeursControls any time you select/unselect a value inside the mat-select component.
try:
getP(event?: Event[]) {
this.valeursControls = [];
if (typeof event == 'undefined') {
this.pSelected = [];
} else {
this.pSelected = event;
this.buildValeursControls();
}
}
private buildValeursControls(){
this.pSelected.forEach(p => {
const VarFormControl = this.fb.control(null);
this.valeursControls.push({
valeur: { n: p, r: this.B.r },
formControl: VarFormControl
});
this.actionFormGroup.addControl(p, VarFormControl );
});
}
private buildForm() {
this.submitted = false;
this.p= this.fb.control('', Validators.required);
this.actionFormGroup = this.fb.group({
p: this.p
});
}
Related
I have a group of checkboxes, and when I click the "select all" checkbox, it works correctly and sets all the checkboxes below, but if I want to clear any other checkboxes, the status of the "All" checkbox will be changed to false, it works internally, but I see that the flag still does not change, why is that?
issue on this image
<div class="checkbox" [ngClass]="classes">
<span *ngIf="label" class="checkbox__title">
{{label | i18next}}
</span>
<label class="checkbox__label" (click)="$event.stopPropagation();">
<input
#checkbox
[value]="value"
[attr.id]="idElement || null"
[attr.disabled]="isDisabled || null"
[attr.checked]="isChecked || null"
[attr.formControlName]="formControlName || null"
(change)="onModelChange($event)"
type="checkbox"
class="checkbox__field"
>
{{text | i18next}}
<span *ngIf="isExtra" class="extra-text">{{extraText | i18next}}</span>
</label>
</div>
this is my code for component:
import {
Component,
ChangeDetectionStrategy,
Input,
Output,
EventEmitter,
ViewChild,
forwardRef, AfterViewInit,
} from '#angular/core';
import { NG_VALUE_ACCESSOR } from '#angular/forms';
import ValidationUtils from '#core/utils/validation/validation.utils';
#Component({
selector: 'ui-checkbox',
templateUrl: './checkbox.component.html',
styleUrls: ['./checkbox.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => CheckboxComponent)
}],
})
class CheckboxComponent<V> extends ValidationUtils.ComponentInputs implements AfterViewInit {
#Input() text: string;
#Input() value: V;
#Input() extraText: string;
#Input() idElement: string;
#Input() label: string;
#Input() classNames: string;
#Input() isExtra = false;
#Input() isDisabled: boolean;
#Input() isChecked: boolean;
#Input() isStrong: boolean;
#Input() formControlName?: string;
#Output() handlerChange = new EventEmitter<{ isChecked: boolean; value: V }>();
#ViewChild('checkbox') checkbox;
requiredFields = ['text', 'value'];
// methods for ControlValueAccessor
onChange: any = () => {
};
onTouch: any = () => {
};
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
writeValue(checked: V): void {
this.value = checked;
}
// end
onModelChange(e): void {
this.value = e.target.value;
this.onChange(this.checkbox.nativeElement.checked);
// call it only if "handlerChange" is passed otherwise don't call it
// it prevents an issue if the parent element has an event listener
// so to prevent double triggering
if (this.handlerChange.observed) {
this.handlerChange.emit({
isChecked: this.checkbox.nativeElement.checked,
value: this.value,
});
}
}
ngAfterViewInit() {
if (this.isChecked !== undefined) {
this.onChange(this.isChecked);
}
}
get classes(): string {
let classes = '';
if (this.isStrong) {
classes += ' checkbox_text-strong';
}
return classes;
}
}
export default CheckboxComponent;
this is code for group of checkboxes:
HTML:
<ui-checkbox
*ngIf="groups.length"
(handlerChange)="toggleAllGroups()"
[isChecked]="isCheckedAllGroups()"
text="common.select_all"
value="All"
></ui-checkbox>
<ui-checkbox
*ngFor="let group of groups"
(handlerChange)="toggleGroup(group.hash)"
[text]="group.name"
[value]="group.hash"
[isChecked]="isCheckedGroup(group.hash)"
></ui-checkbox>
and ts:
toggleGroup(hash: string): void {
let isAdded = false;
const filteredSelectedGroups = this.user.groups.filter((group: GroupModel) => {
if (group.hash !== hash) {
return true;
} else {
isAdded = true;
return false;
}
});
if (!isAdded) {
const fullGroup = this.groups.find((group: GroupModel) => group.hash === hash);
filteredSelectedGroups.push(fullGroup);
}
this.user.groups = filteredSelectedGroups;
}
isCheckedGroup(hash: string) {
return this.user.groups.find((selectedGroup) => {
return selectedGroup.hash === hash;
});
}
toggleAllGroups(): void {
if (this.user.groups.length !== this.groups.length) {
this.user.groups = this.utilService.clone( this.groups);
} else {
this.user.groups = [];
}
}
isCheckedAllGroups(): boolean {
return this.groups.length === this.user.groups.length;
}
I have clients who have their segments (from A to G).
At HomeComponent, I get all these clients. Then they are displayed on the map in MapComponent.
There is also AsideComponent where I have Inputs in the form of Customer Segments (i.e. from A-G, as there are customers).
At this point I have done so that by clicking on Aside I Emit the table of "Segments" clicked to HomaController (argument checkedSegment) and with it I would like to filter all current clients (currentClientList), that is on currentClientList (it has a field called Segment because it is an array of customers) it should contain dynamically all customers that fall within any of the segments.
HomeController :
import { Component, OnInit } from '#angular/core';
import { User } from '../Models/User';
import { UserService } from '../Services/UserServices';
import { Client } from '../Models/Client';
import { ClientService } from '../Services/ClientService';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
currentUser$: User;
currentClientList : Client[];
currentSegments : string[];
checkedSegment: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
currentPH : string[];
checkedPH:string[]= [];
constructor(private user: UserService,private client: ClientService) {
}
ngOnInit(): void {
this.setCurrentUser();
this.getCurrentUser();
this.getClients();
}
setCurrentUser(): void{
const user: User = JSON.parse(localStorage.getItem('user'));
this.user.setCurrentUser(user);
}
getCurrentUser(): void {
// this.currentUser$ = JSON.parse(localStorage.getItem('user'));
this.user.currentUser$.subscribe((response) => {
this.currentUser$ = response;
});
}
getClients(): void {
this.client.getClients()
.subscribe((response) => {
this.currentClientList = response;
this.currentPH = this.removeDuplicatePH(this.currentClientList);
this.onMapNotify(this.currentClientList);
});
}
removeDuplicateSegment(cli: Client[]) {
// tslint:disable-next-line: no-shadowed-variable
const clients = cli.map(clients => clients.segment).sort();
return [...new Set(clients)];
}
removeDuplicatePH(cli: Client[]) {
// tslint:disable-next-line: no-shadowed-variable
const clients = cli.map(clients => clients.ph).sort();
return [...new Set(clients)];
}
onMapNotify(clients: Client[]) : void{
this.currentClientList = clients;
this.currentSegments = this.removeDuplicateSegment(clients);
this.currentPH = this.removeDuplicatePH(clients);
}
recieveCheckedSegment(e) {
console.log(e);
if (e.isChecked === true) {
this.checkedSegment.push(e.segment);
} else {
let i = this.checkedSegment.indexOf(e.segment);
if (i != -1) {
this.checkedSegment.splice(i, 1);
}
}
console.log(this.checkedSegment);
this.filterClients();
}
filterClients() {
console.log("wyfiltrowane przez " + this.checkedSegment);
let currSegmentChecked = this.checkedSegment;
const tempClient = this.currentClientList.map(x => x.segment).filter(function(segment){
return segment.indexOf(segment) >= 0 ;
},currSegmentChecked)
console.log(this.currentClientList.map(x => x.segment));
}
}
Home.Component.hmtl
<div class="wrapper">
<app-header></app-header>
<div class="mainapp">
<app-map class="map" [clientList]= "currentClientList" *ngIf="currentUser$" (klienci)="onMapNotify($event)"></app-map>
<app-aside [Segmenty]= "currentSegments" [PH]= "currentPH" class="aside" *ngIf="currentUser$" (checkedPH)= "recieveCheckedPH($event)"
(checkedSegment)= "recieveCheckedSegment($event)"> {{checkedSegment}} {{checkedPH}}
</app-aside>
</div>
</div>
AsideComponent
import { Component, EventEmitter, Input, OnInit, Output } from '#angular/core';
#Component({
selector: 'app-aside',
templateUrl: './aside.component.html',
styleUrls: ['./aside.component.css']
})
export class AsideComponent implements OnInit {
#Input() Segmenty;
#Output() checkedSegment = new EventEmitter<{}>();
#Input() PH;
#Output() checkedPH = new EventEmitter<{}>();
constructor() {
}
ngOnInit(): void {
}
emitCheckedValue(event, segment) {
// console.log(event.srcElement.checked);
this.checkedSegment.emit({
isChecked: event.srcElement.checked,
segment: segment
});
}
emitCheckedPH(event, ph) {
// console.log(event.srcElement.checked);
this.checkedPH.emit({
isChecked: event.srcElement.checked,
ph : ph
});
}
}
aside.component.html
<div class="box">
<div class="segment">
<div *ngFor ="let segment of Segmenty; let i = index" >
<input type="checkbox" checked="true" (change)="emitCheckedValue($event,segment)">
<span>{{segment}}</span>
</div>
</div>
</div>
Dear I am developing a page with Angular 7 and I am presented with the error TS2559: Type 'BookInterface[]' has no properties in common with type 'BookInterface', I have changed the code but I still can not find the solution, I leave the code below, the error is thrown in the method getListBooks(): this is my file list-books.component.ts
import { BookInterface } from './../../../models/book';
import { DataApiService } from './../../../services/data-api.service';
import { Component, OnInit } from '#angular/core';
import {NgForm} from '#angular/forms';
#Component({
selector: 'app-list-book',
templateUrl: './list-book.component.html',
styleUrls: ['./list-book.component.css']
})
export class ListBookComponent implements OnInit {
constructor(private dataApi: DataApiService) { }
private books: BookInterface = {};
ngOnInit() {
this.getListBooks();
}
getListBooks() {
this.dataApi.getAllBooks().subscribe(books => {
this.books = books;
});
}
onDelete() {
console.log('LIBRO ELIMINADO');
}
}
I also leave the code of my data-api.service.ts from where I call the interface
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs/internal/Observable';
import { Injectable } from '#angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '#angular/fire/firestore';
import { BookInterface } from '../models/book';
#Injectable({
providedIn: 'root'
})
export class DataApiService {
constructor(private afs: AngularFirestore) {
this.bookCollecction = afs.collection<BookInterface>('books');
this.books = this.bookCollecction.valueChanges();
}
private bookCollecction: AngularFirestoreCollection<BookInterface>;
private books: Observable<BookInterface[]>;
private bookDoc: AngularFirestoreDocument<BookInterface>;
private book: Observable<BookInterface>;
getAllBooks() {
return this.books = this.bookCollecction.snapshotChanges()
.pipe(map( changes => {
return changes.map( action => {
const data = action.payload.doc.data() as BookInterface;
data.id = action.payload.doc.id;
return data;
});
}));
}
// metodo que trae un libro a traves de su id
getOneBook(idBook: string) {
this.bookDoc = this.afs.doc<BookInterface>(`books/${idBook}`);
return this.book = this.bookDoc.snapshotChanges().pipe(map(action => {
if (action.payload.exists === false){
return null;
} else {
const data = action.payload.data() as BookInterface;
data.id = action.payload.id;
return data;
}
}));
}
addBook(book: BookInterface): void {
this.bookCollecction.add(book);
}
updateBook(book: BookInterface): void {
let idBook = book.id;
this.bookDoc = this.afs.doc<BookInterface>(`books/${idBook}`);
this.bookDoc.update(book);
}
deleteBook(idBook: string): void {
this.bookDoc = this.afs.doc<BookInterface>(`books/${idBook}`);
this.bookDoc.delete();
}
}
The version of typescript that I am currently using is Version 2.7.2, but also update it without solving the problem
You need to change the following:
private books: BookInterface = {};
to:
private books: BookInterface[] = [];
I have created a mat-table to display list of Jobs.
Now I want to add a mat-filter to search a job using date or JobId.
However the code that I have written doesn't seem to work.
It does not throw any errors and it doesn't filter data.
HTML Code:
<mat-form-field>
<input
matInput
(keyup)="applyFilter($event.target.value)"
placeholder="Search"
/>
</mat-form-field>
<mat-table [dataSource]="jobExecutionList">
...
Typescript Code:
jobExecutionList: any = [];
applyFilter(filterValue: string) {
this.jobExecutionList.filter = filterValue.trim().toLowerCase();
}
Whole Typescript file :
import { Component, OnInit } from "#angular/core";
import { MatTableDataSource } from "#angular/material";
import { GlobalAppSateService } from "../../services/globalAppSate.service";
import { DataService } from "../../services/data.service";
import { SnakBarComponent } from "../custom-components/snak-bar/snak-
bar.component";
import { DataSource } from "#angular/cdk/collections";
import { Observable, of } from "rxjs";
import {
animate,
state,
style,
transition,
trigger
} from "#angular/animations";
import { RecommendationService } from "../recommendation-service.service";
import { MessageService } from '../../services/message.service';
#Component({
selector: "app-job-execution-screen",
templateUrl: "./job-execution-screen.component.html",
styleUrls: ["./job-execution-screen.component.scss"],
animations: [
trigger("detailExpand", [
state(
"collapsed",
style({ height: "0px", minHeight: "0", visibility: "hidden" })
),
state("expanded", style({ height: "*", visibility: "visible" })),
transition(
"expanded <=> collapsed",
animate("225ms cubic-bezier(0.4, 0.0, 0.2, 1)")
)
])
]
})
export class JobExecutionScreenComponent implements OnInit {
displaySpinner: boolean = false;
jobId: string;
jobExecutionList: any = [];
jobExecStatDisplayedColumns = [
"jobId",
"executionDate",
"previousTimePeriod",
"afterTimePeriod",
"status",
"actions",
"spinner"
];
public selectedElem: any;
projectjobId: any = 1;
jobExecutionStat: any;
executionDate: string = new Date().toISOString().slice(0, 10);
executeJobStop: any;
changeStatus: any;
newStatus: any;
isExpansionDetailRow = (i: number, row: Object) =>
row.hasOwnProperty("detailRow");
expandedElement: any;
constructor(
private dataService: DataService,
public globalAppSateService: GlobalAppSateService,
private snakbar: SnakBarComponent,
private recommendationService: RecommendationService,
private messageService: MessageService
) {}
ngOnInit() {
const project = JSON.parse(this.dataService.getObject("project"));
if (project != null) {
this.globalAppSateService.onMessage(project);
}
// API to get list of Running Jobs
this.recommendationService
.getJobExecutionStatList(this.projectjobId)
.subscribe(data => {
this.jobExecutionList = data;
console.log(this.jobExecutionList);
// this.jobExecutionStat = new ExampleDataSource();
});
}
applyFilter(filterValue: string) {
this.jobExecutionList.filter = filterValue.trim().toLowerCase();
}
stop_exec_job(element) {
if (element.status == "Running" || element.status == "Pending") {
//Api to stop Job Execution
this.recommendationService
.stopJobExecution(element.jobId, "Cancelled")
.subscribe(data => {
this.executeJobStop = data;
//this.changeStatus.push(this.executeJobStop);
// this.newStatus = new ExampleDataSource();
});
this.displaySpinner = false;
element.status = "Cancelled";
this.snakbar.statusBar("Job Execution Stopped", "Sucess");
} else {
this.snakbar.statusBar("Job Failed to start", "Failure");
}
}
// Will need it for mat-progress bar
// stop_exec_job2() {
// this.stop_exec_job(this.selectedElem);
// this.displaySpinner = false;
// }
re_run_job(element) {
if (
element.status == "Cancelled" ||
element.status == "Completed" ||
element.status == "Executed" ||
element.status == "FINISHED"
) {
//Api to Re-Run Job Execution
this.recommendationService
.stopJobExecution(element.jobId, "Running")
.subscribe(data => {
this.executeJobStop = data;
//this.changeStatus.push(this.executeJobStop);
// this.newStatus = new ExampleDataSource();
});
this.displaySpinner = true;
element.status = "Running";
this.snakbar.statusBar("Job Execution Started", "Sucess");
this.messageService.messageReceived$.subscribe(data => {
this.snakbar.statusBar(
'Platform job status - ' + data,
'Info'
);
//this.isLoadingResults = false;
});
} else {
this.snakbar.statusBar("Job Failed to start", "Failure");
}
}
}
export interface Element {
jobId: number;
executionDate: string;
previousTimePeriod: string;
afterTimePeriod: string;
status: string;
}
This is the Whole typescript file.
Based on different comment, you need to do:
dataSource: MatTableDataSource<any>;
And then when you get the data:
this.dataSource = new MatTableDataSource(/** YOUR DATA **/);
In your example:
import { Component, OnInit } from "#angular/core";
import { MatTableDataSource } from "#angular/material";
import { GlobalAppSateService } from "../../services/globalAppSate.service";
import { DataService } from "../../services/data.service";
import { SnakBarComponent } from "../custom-components/snak-bar/snak-
bar.component";
import { DataSource } from "#angular/cdk/collections";
import { Observable, of } from "rxjs";
import {
animate,
state,
style,
transition,
trigger
} from "#angular/animations";
import { RecommendationService } from "../recommendation-service.service";
import { MessageService } from '../../services/message.service';
#Component({
selector: "app-job-execution-screen",
templateUrl: "./job-execution-screen.component.html",
styleUrls: ["./job-execution-screen.component.scss"],
animations: [
trigger("detailExpand", [
state(
"collapsed",
style({ height: "0px", minHeight: "0", visibility: "hidden" })
),
state("expanded", style({ height: "*", visibility: "visible" })),
transition(
"expanded <=> collapsed",
animate("225ms cubic-bezier(0.4, 0.0, 0.2, 1)")
)
])
]
})
export class JobExecutionScreenComponent implements OnInit {
displaySpinner: boolean = false;
jobId: string;
jobExecutionList: MatTableDataSource<any>;
jobExecStatDisplayedColumns = [
"jobId",
"executionDate",
"previousTimePeriod",
"afterTimePeriod",
"status",
"actions",
"spinner"
];
public selectedElem: any;
projectjobId: any = 1;
jobExecutionStat: any;
executionDate: string = new Date().toISOString().slice(0, 10);
executeJobStop: any;
changeStatus: any;
newStatus: any;
isExpansionDetailRow = (i: number, row: Object) =>
row.hasOwnProperty("detailRow");
expandedElement: any;
constructor(
private dataService: DataService,
public globalAppSateService: GlobalAppSateService,
private snakbar: SnakBarComponent,
private recommendationService: RecommendationService,
private messageService: MessageService
) {}
ngOnInit() {
const project = JSON.parse(this.dataService.getObject("project"));
if (project != null) {
this.globalAppSateService.onMessage(project);
}
// API to get list of Running Jobs
this.recommendationService
.getJobExecutionStatList(this.projectjobId)
.subscribe(data => {
this.jobExecutionList = new MatTableDataSource(data);
console.log(this.jobExecutionList);
// this.jobExecutionStat = new ExampleDataSource();
});
}
applyFilter(filterValue: string) {
this.jobExecutionList.filter = filterValue.trim().toLowerCase();
}
I already have an example for this kind, you can look over this.
Mat-Table-stackblitz
I know this question has been asked several times, but problem is that nobody tried to make a some fiddle or show results of code. This is what i have, i need to update values in other component based on value in some other component, but that is not just value,I have call function again in some other component.
I have some component that goes to database and update values, on second hand I have other component that read those values from database from service.
This is example of my code
tasks.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { environment } from '../../environments/environment';
import { Tasks } from './tasks';
#Injectable()
export class TasksProvider {
constructor(private http: HttpClient) { }
createNewTask(name: Name) : Observable<any> {
return this.http.post(environment.apiUri + 'tasks', { name, finished: false },
{ responseType: 'text' });
}
updateTask(id: Id, name: Name, finished: boolean) : Observable<any> {
return this.http.put(environment.apiUri + 'tasks/' + id, { name, finished },
{ responseType: 'text' });
}
getAllTasks(): Observable<Tasks[]> {
return this.http.get(environment.apiUri + 'tasks')
.map<any, Tasks[]>(data => data.map(Tasks.fromObject));
}
}
app.component.html
<app-tasks-list></app-tasks-list>
<app-tasks-add-new></app-tasks-add-new>
As you may see I have not child components, that is my main problem
tasks-list.component.ts
import {Component} from '#angular/core';
import { Tasks } from '../services/tasks';
import { TasksProvider } from '../services/tasks.service';
#Component({
selector: 'app-tasks-list',
templateUrl: './tasks-list.component.html',
styleUrls: ['./tasks-list.component.scss']
})
export class TasksListComponent {
tasks: Array<Tasks>;
constructor(private tasksProvider: TasksProvider) { }
ngOnInit() {
this.getTasksList();
}
displayedColumns: string[] = ['id', 'name', 'finished'];
private getTasksList() {
this.tasksProvider.getAllTasks()
.subscribe(tasks => {
this.tasks = tasks;
});
}
public updateCheckboxValue(id: number, name: string, event: any){
this.tasksProvider.updateTask(id, name, event.checked).subscribe(
result => {},
() => {
alert('Something went wrong');
})
}
}
tasks-add-new.component.ts
import { Component, OnInit, Inject } from '#angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '#angular/material';
import { Tasks } from '../services/tasks';
import { TasksProvider } from '../services/tasks.service';
export interface DialogData {
name: string;
}
#Component({
selector: 'app-tasks-add-new',
templateUrl: './tasks-add-new.component.html',
styleUrls: ['./tasks-add-new.component.scss']
})
export class TasksAddNewComponent implements OnInit {
ngOnInit() {
}
constructor(public dialog: MatDialog, private tasksProvider: TasksProvider) {}
openDialog(): void {
const dialogRef = this.dialog.open(TasksAddNewDialog, {
width: '250px',
data: {name: this.animal}
});
dialogRef.afterClosed().subscribe(result => {
this.name = result
this.tasksProvider.createNewTask(this.name).subscribe(
result => {},
() => {
alert('Something went wrong');
})
}
}
}
#Component({
selector: 'tasks-add-new-dialog',
templateUrl: 'tasks-add-new-dialog.html'
})
export class TasksAddNewDialog {
constructor(
public dialogRef: MatDialogRef<TasksAddNewDialog>,
#Inject(MAT_DIALOG_DATA) public data: DialogData) {}
onNoClick(): void {
this.dialogRef.close();
}
}
You see now when i call function in tasks-add-new.component.ts like
this.tasksProvider.createNewTask(this.name).subscribe(
result => {},
() => {
alert('Something went wrong');
})
I need to call again function in tasks-list.component.ts
private getTasksList() {
this.tasksProvider.getAllTasks()
.subscribe(tasks => {
this.tasks = tasks;
});
}
Does any body have idea how i can do that the best practice?
On of the possible approach is to use Subjects.
1) Store task list on the service and provide subscribable Subject
private tasks: Array<Task>;
public $tasks: BehaviorSubject<Array<Task>>;
constructor(private http: HttpClient) {
this.$tasks = new BehaviorSubject([]);
...
}
getAllTasks() {
this.http.get(environment.apiUri + 'tasks')
.subscribe(data => {
this.tasks = data;
this.$tasks.next(this.tasks);
});
}
updateTask(params) {
this.http.post(/* params */).subscribe((task) => {
this.tasks = this.tasks.map(t => t.id !== task.id ? t : task);
this.$tasks.next(this.tasks);
});
}
createTask(...) {
// again, do a request, update this.tasks and call $tasks.next
...
}
2) Make one service Subject subscription on the component instead of multiple service methods Observable listeners and update component's list automatically each time the service source has been changed
tasks: Array<Tasks>;
constructor(private tasksProvider: TasksProvider) {
this.tasksProvider.$tasks.subscribe(tasks => this.tasks = tasks);
}
ngOnInit() {
this.tasksProvider.getAllTasks();
}
public updateCheckboxValue(id: number, name: string, event: any){
this.tasksProvider.updateTask(id, name, event.checked);
}