Angular 4. Github source
I have a menu which is filled by a web service. The web service is in taskService, but is not necessary now.
ngOnInit() {
this.getTasks();
}
getTasks(): void {
this.taskService.getTasks()
.subscribe(Tasks => this.tasks = Tasks);
}
When you click on a task it loads a page, a different component, with a form ready to update the data. It is also made by a web service and works fine. The problem is that after update the task, it is not reflected in the task menu
I am importing this:
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
and adding this to the constructor:
private cdRef: ChangeDetectorRef
And this is my best approach to the detectChanges() function, after update the data with the save() function
this.taskService.updateTask(task, id)
.subscribe(
this.Ref.detach();
setInterval(() => {
this.Ref.detectChanges();
}, 5000);
);
This is the html from the menu to print the tasks:
<li *ngFor="let task of tasks" class="d-inline-block col-md-12">
<a routerLink="/task/{{task.id}}" > {{task.title}}</a>
<!-- <span class="close big"></span> -->
<button class="close big" title="delete task"
(click)="delete(task)">x</button>
</li>
And this is the form that updates the task
<form (ngSubmit)="save(taskName.value, taskBody.value)" #taskForm="ngForm" class="example-form">
<mat-form-field class="example-full-width">
<label>Task Name</label>
<input matInput [(ngModel)]="task.name" #taskName name="name">
</mat-form-field>
<mat-form-field class="example-full-width">
<textarea matInput [(ngModel)]="task.body" #taskBody name="body"></textarea>
</mat-form-field>
<button type="submit" class="btn btn-success" >Save</button>
</form>
Both are in different components.
I have tried to follow this tutorial, but I'm stuck, I don't know how to use the ChangeDetectorRef.
I've looked at your code. The problem is that the view-task.component
updates your tasks, but the navigation.component
is not notified about this transaction. I think BehaviorSubject
might be just the thing for you.
You can read more about it here
I assume you would have single array of tasks
throughout your application and you would display them on your navigation
component.
Task.service.ts
export class TaskService {
// behaviorSubject needs an initial value.
private tasks: BehaviorSubject = new BehaviorSubject([]);
private taskList: Task[];
getTasks() {
if (!this.taskList || this.taskList.length === 0) {
this.initializeTasks();
}
return this.tasks.asObservable();
}
initializeTasks() {
this.http.get('api/tasks')
.subscribe(tasks => {
// next method will notify all of the subscribers
this.tasks.next(tasks);
}, error => {
// proper error handling here
});
}
updateTasks(task: Task) {
this.http.post('api/updateTask')
.subscribe(resp => {
// update your tasks array
this.tasks = ...
// and call next method of your behaviorSubject with updated list
this.tasks.next(this.tasks);
}, error => {
// proper error handling here
});
}
}
Navigation.component.ts
export class NavigationComponent implements OnInit{
tasks: Task[];
constructor(private taskService: TaskService) {}
ngOnInit() {
// this method will be called every time behaviorSubject
// emits a next value.
this.taskService.getTasks()
.subscribe(tasks => this.tasks = tasks);
}
}
View-task.component.ts
export class ViewTaskComponent {
constructor(private taskService: TaskService) {}
updateTask(task: Task) {
this.taskService.updateTask(task);
}
}
I haven't tried this code myself. However, I have implemented something similar on my application before. So when you try it and have a problem, let me know.