Reputation: 149
I have been trying to return some users info and to display them trough HTML. But I am getting the error: "Cannot read property 'firstname' of null" error" To store data I am using MongoDB, for the backend service Express and Node.js and for the frontend Angular. To communicate between back and frontend I delegated that to HttpClient. Connection with Mongo works fine since my console receiving all data but when it comes to the frontend side it's giving me this issue.
routes-index.js class method for connection with MongoDB
router.get('/tasks', async (req, res) => {
let MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
res.json([
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('angular-auth');
dbo.collection('users').find({}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
//db.close;
});
})
])
});
tasks.service.ts class method for returning data to frontend
getTasks() {
return this.httpClient.get<any>(this.URL + '/tasks');
}
private-tasks.component.ts class ngOnInit() method which supposes to get and to subscribe data
ngOnInit(): void {
this.tasksService.getTasks()
.subscribe(
res => {
console.log(res); //<===== this line is returning null value!
this.tasks = res;
},
err => console.log(err)
);
}
private-tasks.component.html class
<ul class="list-group">
<li class="list-group-item" *ngFor='let task of tasks'>
{{task.firstname}}
</li>
</ul>
console.log(res); gives null value, but within if/else statement it's actually not null... How I am sure that is not... coz the same method is giving me output in the console. I have tried also to add ? to {{task?.firstname}} in that way I am not getting any error but still console.log(res); gives null value.
Is there anything that you can suggest how to approach this problem?
Upvotes: 1
Views: 1764
Reputation: 1
I had the same problem and deleted the sessions in mongodb, the problem was solved.
Upvotes: 0
Reputation: 19754
The culprit is the res.json
call on the back-end side. The front-end side of the code seems good. The argument of the function call is supposed to be an object that you return from the server to the client, but what you'\re giving it instead if whatever MongoClient.connect returns -- which is probably nothing (I've never used it so I can't be sure).
The place where you call console.log
is inside the innermost callback function. At the moment this piece of code runs, the database has responded and the response is ready to be sent to the client. But you attempt to send the data to the client before this callback is run.
So the correct approach is to place res.json
inside the innermost callback, which runs when the data is available.
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('angular-auth');
dbo.collection('users').find({}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
res.json(result); // <-- res.json goes inside, after data is available
});
});
Upvotes: 1
Reputation: 53
This sounds like an Async issue, here is what you can try in your service.ts file:
private tasks:TaskModel[] = []
import {Subject} from 'rxjs';
and
private taskUpdated = new Subject<taskModel>[](); //create a new subject of type taskModel that you will add to
getTasks(){
this.httpClient.get<any>(this.URL + '/tasks')
.subscribe((taskData)=> {
this.taskNotes = taskData;
this.taskUpdated.next([...this.taskNotes])//adding in taskNotes
})
getTasksUpdatedAsListener(){
return this.taskUpdated.asObservable();//observable that you will subscribe to in component.ts
}
//subscription that needs to be created
private sub:Subscription;
ngOnInit(): void {
this.tasksService.getTasks()//this needs to go first. It will get data in the service file
this.sub = this.taskService.getTasksUpdatedAsListener()
.subscribe((data TaskModel[])=> {
console.log(data);//you should see the data come in as json
})
}
Let me know how it goes!
Upvotes: 0