Issue
I created backend in Node.js and frontend in angular2+. I want to do a simple todo-list. I made a GET, POST, and DELETE methods, and these works correctly. The problem is when I subscribe my getTodos
function, I not getting any updates when todosList is changed by POST or DELETE in the meanwhile.
Here is the code for todo.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Todo } from '../models/todo.model';
@Injectable()
export class TodoService {
constructor(private http: HttpClient) { }
getTodos(): Observable<Todo[]> {
const baseUrl = 'http://localhost:3000/'
const todoUrl = 'api/todo'
return this.http.get<Todo[]>(baseUrl + todoUrl)
}
}
Have typescript code app.component.ts
const baseUrl = 'http://localhost:3000/'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
providers: [ TodoService ]
})
export class AppComponent implements OnInit {
title = 'todo';
taskHeader = ['User', 'Todo', 'Is done', 'Has attachment']
todos: Todo[];
constructor(private http: HttpClient, private todoService: TodoService) {}
ngOnInit() {
this.todoService.getTodos()
.subscribe((res) => {this.todos = res
console.log('this.todos', this.todos)}
)
}
send(data) {
const addUserUrl = 'api/todo'
let addUserHeaders = new HttpHeaders().append('Content-Type', 'application/json');
const todo: Todo = {
userName: 'test',
todo: data,
isDone: true,
hasAttachment: false
}
this.http.post(baseUrl + addUserUrl, todo, {headers: addUserHeaders, responseType: 'text'}).subscribe((x) => console.log(x) )
}
deleteTask(todoId) {
const addUserUrl = 'api/todo'
this.http.delete(`${baseUrl}${addUserUrl}/${todoId} `, {responseType: 'text'}).subscribe((s) => {
console.log(s);
})
}
}
Here is api.controller.js
module.exports = (app) => {
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.get('/api/todo', (req, res) => {
Todos.find({}).then(function (todos) {
res.send(todos);
});
})
app.post('/api/todo', (req, res) => {
if (req.body.id) {
Todos.findByIdAndUpdate(req.body.id, {
todo: req.body.todo, isDone:
req.body.isDone, hasAttachment:
req.body.hasAttachment
},
(err, todo) => {
if (err) throw err
res.send('Post Success')
})
}
else {
const newTodo = Todos({
userName: req.body.userName,
todo: req.body.todo,
isDone: req.body.isDone,
hasAttachment: req.body.hasAttachment
})
newTodo.save((err) => {
if (err) throw err
res.send('Post Success')
})
}
});
app.delete('/api/todo/:id', (req,res) => {
Todos.findByIdAndRemove(req.params.id, (err) => {
if (err) throw err
res.send('Delete Success')
})
})
}
Solution
Subscribe
doesn’t work the way you think. If you subscribe to getTodos
the request gets sent once, you get the response and that’s it. There is no connection anymore that would get notified about any change in your database when there is a post/delete request.
You have several options:
- whenever you make a post/delete request instead of sending
Post Success
orDelete Success
as a response you send the database content. - after a successful post/delete request you modify the data in your frontend
- you use websockets as a steady connection between your frontend and backend. this options comes close to how you think
subscribe
works
Personally I would implement the first or second option.