retrieve a function from a Firestore service

Is there a way to utilize a function from a service within a component? I am attempting to use the following code:

 addProyecto(proyecto: Proyecto) {
    this.proyectosCollection.add(this.proyecto);
}

However, I am encountering this error message:

TypeError: Cannot read property 'add' of undefined
    at ProyectosService.addProyecto

I'm looking to add a document to a Firestore collection. While I can achieve this directly in the component, I'm struggling to do so using a service.

Any suggestions?

proyecto.ts

export interface Proyecto {
    titulo?: string;
    destacado?: string;
    descripcion?: string;
}

export interface ProyectoId extends Proyecto {
    id: string
};

proyecto.service.ts

import { Injectable } from '@angular/core';
import { Proyecto } from './proyecto';

//Firestore
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Observable';


@Injectable()
export class ProyectosService {

    proyecto: Proyecto = {};
    proyectosCollection: AngularFirestoreCollection<Proyecto>;
    proyectosObservable: Observable<Proyecto[]>;

    constructor(private afs: AngularFirestore) { 

    }

    getProyectos() {
        this.proyectosCollection = this.afs.collection('proyectos', ref => ref.orderBy('titulo'));

        this.proyectosObservable = this.proyectosCollection.snapshotChanges().map(arr => {
            return arr.map(snap => {
                const data = snap.payload.doc.data() as Proyecto;
                const id = snap.payload.doc.id;
                return { id, ...data };
            });
        });
        return this.proyectosObservable;
    };

    addProyecto(proyecto: Proyecto) {
        this.proyectosCollection.add(this.proyecto);
    }

}

crear-proyecto.component.ts

import { Component, OnInit } from '@angular/core';
import { ProyectosService } from '../proyectos.service';
import { Proyecto } from '../proyecto';

import { Observable } from 'rxjs/Observable';
import { AngularFirestoreCollection, AngularFirestore } from 'angularfire2/firestore';


@Component({
    selector: 'app-crear-proyecto',
    templateUrl: './crear-proyecto.component.html',
    styleUrls: ['./crear-proyecto.component.scss'],
    providers: [ProyectosService]
})
export class CrearProyectoComponent implements OnInit {


    proyecto: Proyecto = {};
    proyectosCollection: AngularFirestoreCollection<Proyecto>;
    proyectosObservable: Observable<Proyecto[]>;

    constructor(private sp: ProyectosService, private afs: AngularFirestore) {}

    ngOnInit() {
    }

    agregarProyecto() {
        this.sp.addProyecto(this.proyecto)
    }
}

Answer №1

The reason why your this.proyectosCollection is undefined is because you have defined it inside the function getProyectos(). It will remain undefined until this function is called.

To fix this issue, you should move your collection initialization to the ngOnInit() method in the proyecto.service.ts file:

ngOnInit() {
    this.proyectosCollection = this.afs.collection('proyectos', ref => ref.orderBy('titulo'));
}

Your get function should look like this:

getProyectos() {
    this.proyectosObservable = this.proyectosCollection.snapshotChanges().map(arr => {
        return arr.map(snap => {
            const data = snap.payload.doc.data() as Proyecto;
            const id = snap.payload.doc.id;
            return { id, ...data };
        });
    });
    return this.proyectosObservable;
};

Once you make these changes, you can now call addProyecto().

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Running multiple versions of the Angular CLI on one machine

In my various Angular2 projects, I am faced with the challenge of working with different versions of angular-cli. This means that in order to run and compile each project for production, I need to ensure that the correct version of angular-cli is being use ...

Guide on creating a custom command within the declaration of Tiptap while extending an existing extension with TypeScript

I'm currently working on extending a table extension from tiptap and incorporating an additional command. declare module '@tiptap/core' { interface Commands<ReturnType> { table: { setTableClassName: () => ReturnType; ...

Error Alert: You have entered 'undefined' instead of a valid input

@Input() changeStoreKeyToChangeTypeMapping:Map<any,any>; ngOnInit() { this.configToMetadataMap = new Map<any,any>(); this.getAllConfigMetaData().subscribe(_ => this.initialize()); } private getAllConfigMetaData(): Observable<any ...

Angular forms with bootstrap can utilize the 'is-invalid' and 'is-valid' classes for added validation features

Consider a scenario where I have a small form and am using a reactive approach. For instance, there are two input fields: ... <input formControlName="name" name="name" type="text" class="form-control"> <input formControlName="amount" name="amount ...

Using React to Identify the Chosen Option on a Custom Toggle Button

I have successfully implemented a toggle switch using HTML and CSS in my React app. I am now looking for a way to detect the selected option whenever it changes. For instance, if OR is chosen, I would like it to be saved in the selectedOption state, and if ...

Error encountered in EBS Node.js 14: TS5033 - Unable to save file due to EACCES error related to permission denial

Upon creating a new EBS environment with Node.js 14 to replace the deprecated old one, I encountered the following error: Jul 27 22:34:53 ip-172-31-42-207 web: error TS5033: Could not write file '/var/app/current/build/server/validation.js.map': ...

Could not locate a client that matches the package name 'com.example.pc.fireApp'

Whenever I try to sync my Graddle, I encounter an error related to the google-service.json file. The error states: "No matching client found for package name 'com.example.pc.fireApp'". Here is my Graddle configuration: apply plugin: 'c ...

Working with Ngxs and WebSocket: How to intercept the connection and include a custom HTTP header

Currently, I am utilizing ngxs's NgxsWebsocketPluginModule to establish a websocket connection within my Angular application. In order to authenticate the connecting client, my server mandates an authentication token to be included in the HTTP headers ...

Unveiling the power of experimental decorators in Storybook 8 with NextJS/SWC

I am facing an issue with experimental class decorators in my code, causing the Storybook build to crash. Module build failed (from ./node_modules/@storybook/nextjs/dist/swc/next-swc-loader-patch.js): Error: × Expression expected Despite reading the co ...

Can you send the value of an Angular-generated input to a function even if it doesn't have an ID associated with it?

Is there a way to make the cells in a dynamically generated table editable? The challenge I am facing is that because the table uses MatTableDataSource in Angular with data from an API, the cell elements cannot have unique IDs. How can I ensure that when a ...

Sharing data between two AngularJS components using TypeScript

I am working with two components: export const TopBarMemberComponent: angular.IComponentOptions = { bindings: {}, require: { controller: '^EngagementSetupMember' }, templateUrl: 'topBarMembers.com ...

Issue with retrieving relative time using Moment.js - fromNow()

I want to utilize moment.js to display relative time fromNow(), but I am encountering an issue where the values are being rounded and showing higher durations instead of exact completion times. For example, moment().subtract('s',110).fromNow() / ...

How can I showcase a timestamp data type element that I fetched from Firestore?

Currently, I am looking to showcase the data stored in my Firestore collection. One crucial element in this collection is the "date" field, which is categorized as timestamp. However, upon attempting to display these values, an error message surfaces: E ...

Struggling to apply filtering on an array containing multiple objects within Ionic 2

I have successfully implemented filtering on the following array: this.items = [ 'Amsterdam', 'Bogota', 'India' ]; The code used in my list.ts file is as follows: if (val && val.trim() != '') { thi ...

Passport.js, solving the Auth0 CORS issue

I am currently working on setting up a single page application using Angular 5 and Express, with authentication through Passport.js and Auth0. However, I keep encountering an error when attempting to log in: Failed to load the following URL: : The r ...

Utilizing Angular 2 Component Input Binding with the Expression Mapping Function

Currently, I am working on a component that has an input of type array. class FooComponent { @Input() selectedItemIds:String[]; } I want to utilize a map expression in binding within the parent component. <app-foo-component [selectedItemIds]=&apo ...

"Authentication guard does not sit idle while waiting for the observable

My issue involves the auth guard service constructor(private _auth: AuthService, private _router: Router) { } canActivate() { if(this._auth.isLoggedIn()){ return true; } else { this._router.navigate(['/login']); ret ...

Avoiding duplicate subscriptions in Angular 4/5: a guide to streamlining

I'm looking for a streamlined way to capture a query parameter and subscribe to an API in order to retrieve results. Currently, I am using combineLatest but it seems a bit excessive. Is there a more efficient approach that focuses solely on the queryP ...

What is the best way to incorporate Express following an asynchronous function?

After setting up my Firebase and initializing it, I managed to retrieve data from it. However, I encountered an issue when trying to use express.get() and json the data into the server. I'm unsure of what the problem could be. let initializeApp = requ ...

How to deduce a string literal using a ternary conditional in TypeScript

Here is a simple illustration: function doSomething(animal: 'bird' | 'fish'){ } let flies=true; const animal = flies ? 'bird' : 'fish' doSomething(animal); In the assignment to `animal` from the ternary conditio ...