I'm building an application with Angular for client side and Firebase for back-end. What I'm trying to do is to retrieve a single object from AngularFirestore. But unfortunately the server response with a empty array and with
Object { initialTeardown: undefined, closed: false, _parentage: null, _finalizers: (1) […], isStopped: false, destination: {…} }
This is my estateService file, all other methods works only the method getById()
didn't works as expected
import { Injectable } from '@angular/core';
import {
AngularFirestore,
AngularFirestoreCollection,
} from '@angular/fire/compat/firestore';
import { Estate } from '../models/estate.model';
@Injectable({
providedIn: 'root',
})
export class EstateService {
private dbPath = '/estates';
estatesRef: AngularFirestoreCollection<Estate>;
constructor(private db: AngularFirestore) {
this.estatesRef = db.collection(this.dbPath);
}
getAll(): AngularFirestoreCollection<Estate> {
return this.estatesRef;
}
getById(estateId: string): AngularFirestoreCollection<Estate> {
return this.db.collection<Estate>('estates', ref => ref.where('id', '==', estateId));
}
getByUser(userId: string): AngularFirestoreCollection<Estate> {
return this.db.collection<Estate>('estates', ref => ref.where('owner', '==', userId));
}
create(estate: Estate): any {
return this.estatesRef.add({...estate});
}
update(id: string, data: any): Promise<void> {
return this.estatesRef.doc(id).update(data);
}
delete(id: string): Promise<void> {
return this.estatesRef.doc(id).delete();
}
}
And this is the estate-details component where I'm trying to implement and use the single object.
@Component({
selector: 'app-estate-details',
templateUrl: './estate-details.component.html',
styleUrls: ['./estate-details.component.scss'],
})
export class EstateDetailsComponent {
estate: Estate | undefined;
constructor(
private estateService: EstateService,
private activatedRoute: ActivatedRoute
) {
this.fetchSingleEstate();
}
fetchSingleEstate(): void {
this.estate = undefined;
const estateId = this.activatedRoute.snapshot.params['id'];
const estateAr = this.estateService.getById(estateId);
console.log(
estateAr.snapshotChanges().pipe(
map((changes) =>
changes.map((e) => ({
...(e.payload.doc.data() as Estate),
id: e.payload.doc.id,
}))
)
).subscribe((data) => {
console.log(data);
})
);
}
}
this.activatedRoute.snapshot.params['id'] returns the correct Id. I searched for a information but didn't find any solution that works in my case.
All checked solutions: Angular | Get one row from Firebase , How i can get single record with ID , How to get one doc by id , Docs
Any help will be appreciated! Thank you in advance!
After a long research the following do the job for me. Instead of new request to the server I've created a setActive()
method in the objects list component. And whit this method I'm just taking the currentObject
and the currentObjectIndex
.
@Component({
selector: 'app-estates',
templateUrl: './estates.component.html',
styleUrls: ['./estates.component.scss'],
animations: [pageAnimations]
})
export class EstatesComponent implements OnInit {
arrayEstate?: Estate[];
currentEstate?: Estate;
currentIndex = -1;
constructor(
private estateService: EstateService,
private authService: AuthService
) {
this.retrieveEstates()
}
ngOnInit(): void {
}
refreshList(): void { // Used to set the active estate to null
this.currentEstate = undefined;
this.currentIndex = -1;
this.retrieveEstates();
}
setActiveEstate(estate: Estate, index: number): void {
this.currentEstate = estate;
this.currentIndex = index;
}
}
And just passing the current estate to the child component(Which in my case is EstateDetailsComponent) using the @Input
decorator. And with the help of the OnChanges
lifecycle hook just listen for changes in the currentObject
value. If any changes just pass them to the currentEstate
property in my child component.
@Component({
selector: 'app-estate-details',
templateUrl: './estate-details.component.html',
styleUrls: ['./estate-details.component.scss'],
// animations: [bounceIn],
})
export class EstateDetailsComponent implements OnInit {
@Input() estate?: Estate;
@Output() refreshList: EventEmitter<any> = new EventEmitter();
@ViewChild(NgForm, { static: true }) form!: ElementRef<HTMLInputElement>;
currentEstate: Estate = {
address: '',
city: '',
zip: '',
bedrooms: 0,
baths: 0,
type: '',
price: 0,
rented: true,
maintenance: false,
};
constructor(private estateService: EstateService) {}
ngOnChanges(): void {
this.currentEstate = { ...this.estate };
}
updateEstate(form: NgForm): void { //Edit single object
const data = {
id: this.currentEstate.id,
owner: this.currentEstate.owner,
...form.value,
};
if (this.currentEstate.id) {
this.estateService
.update(this.currentEstate.id, data)
.then(() => this.toggleEditMode())
.catch((err) => console.log(err));
}
}
unsetEstate(): void {
this.refreshList.emit();
}
}
This is a way more flexible than taking the single object with server request. Hope someone else find this helpful too.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.