it is passed a lot of time from the last time that I worked on Angular and Firebase and I am finding the following simple problem trying to use AngularFire 2 in order to retrieve the entire objects from a Firestore collection (it means the document ID the document data that must be put into a model object).
So this is my situation.
First of all this is my package.json file:
{
"name": "fintness-tracker",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "~13.3.0",
"@angular/cdk": "^13.3.8",
"@angular/common": "~13.3.0",
"@angular/compiler": "~13.3.0",
"@angular/core": "~13.3.0",
"@angular/flex-layout": "^13.0.0-beta.38",
"@angular/forms": "~13.3.0",
"@angular/material": "^13.3.8",
"@angular/platform-browser": "~13.3.0",
"@angular/platform-browser-dynamic": "~13.3.0",
"@angular/router": "~13.3.0",
"angularfire2": "^5.4.2",
"firebase": "^7.24.0",
"hammerjs": "^2.0.8",
"rxjs": "~7.5.0",
"rxjs-compat": "^6.6.7",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~13.3.6",
"@angular/cli": "~13.3.6",
"@angular/compiler-cli": "~13.3.0",
"@types/jasmine": "~3.10.0",
"@types/node": "^12.11.1",
"jasmine-core": "~4.0.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.1.0",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.6.2"
}
}
Then I have this simple Exercise model interface that will map a Firebase document:
export interface Exercise {
id: string;
name: string;
duration: number;
calories: number;
date?: Date;
state?: 'completed' | 'cancelled' | null;
}
And finally my NewTrainingComponent Angular component class, in its ngOnInit()
import { Component, OnInit, EventEmitter, Output } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Exercise } from '../exercise.model';
import { TrainingService } from '../training.service';
import { AngularFirestore } from 'angularfire2/firestore';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-new-training',
templateUrl: './new-training.component.html',
styleUrls: ['./new-training.component.css']
})
export class NewTrainingComponent implements OnInit {
@Output()
trainingStart:EventEmitter<void> = new EventEmitter<void>();
//exercises: Exercise[] = [];
exercises: Observable<any>;
constructor(private trainingService: TrainingService,
private db: AngularFirestore) { }
ngOnInit(): void {
//this.exercises = this.trainingService.getAvailableExercises();
//this.exercises = this.db
this.db
.collection("availableExercises")
.snapshotChanges()
.pipe(
map((docArray) => {
return docArray.map((doc) => {
return {
id: doc.payload.doc.id,
...(doc.payload.doc.data() as Exercise),
};
});
})
)
.subscribe(result => {
console.log(result);
});
/*
this.db.collection('availableExercises').valueChanges().subscribe(result => {
console.log(result);
})
*/
}
onStartTraining(form: NgForm) {
this.trainingService.startExercise(form.value.exercise);
}
}
What is the problem?
The problem is that when I try to create my model object in this way:
return {
id: doc.payload.doc.id,
...(doc.payload.doc.data() as Exercise),
};
it give me the following error on the id property on my IDE:
'id' is specified more than once, so this usage will be overwritten.ts(2783)
Compiling I obtain the same error:
Error: src/app/training/new-training/new-training.component.ts:38:15 - error TS2783: 'id' is specified more than once, so this usage will be overwritten.
38 id: doc.payload.doc.id,
~~~~~~~~~~~~~~~~~~~~~~
src/app/training/new-training/new-training.component.ts:39:15
39 ...(doc.payload.doc.data() as Exercise),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This spread always overwrites this property.
Error: src/app/training/new-training/new-training.component.ts:38:15 - error TS2783: 'id' is specified more than once, so this usage will be overwritten.
38 id: doc.payload.doc.id,
~~~~~~~~~~~~~~~~~~~~~~
src/app/training/new-training/new-training.component.ts:39:15
39 ...(doc.payload.doc.data() as Exercise),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This spread always overwrites this property.
✖ Failed to compile.
If I remove this property and I use:
return {
//id: doc.payload.doc.id,
...(doc.payload.doc.data() as Exercise),
};
I obtain no error but when the console.log() print out my result it doesn't contains the id property.
Why? What is wrong with my code? What am I missing? How can I try to fix it?
CodePudding user response:
This is because you have an id
property in your Exercice
interface.
Switching the order as follows should do the trick, according to this SO answer (I didn't test it):
return {
...(doc.payload.doc.data() as Exercise),
id: doc.payload.doc.id
};