web-dev-qa-db-fra.com

Firestore: Ajouter un objet personnalisé à la base de données

Bonjour,

J'ai essayé d'ajouter un nouvel objet créé à partir de cette classe:

export class Sponsor implements ISponsor {

  title: string;    
  description?: string;
  creation: ICreation;

  constructor(title: string, description: string, author: string) {
     this.title = title;
     this.description = description;
     this.creation = new Creation(author);
  }
}

et à mon service, la fonction de création ressemble à:

createSponsor(sponsor) {
   sponsor.id = this.afs.createId();
   return this.collection.doc(sponsor.id).set(sponsor);
}

Lorsque j'essaie de cette façon, j'obtiens l'erreur suivante: 

FirebaseError: [code = argument-non valide]: Fonction DocumentReference.set () appelée avec des données non valides. Les données doivent être un objet, mais c'était: un objet sponsor personnalisé

Comment puis-je résoudre ce problème?

13
Coach

Vous pouvez également utiliser Object.assign ({}, sponsor).

donc dans votre cas ce serait 

this.collection.doc(sponsor.id).set(Object.assign({}, sponsor));
19
sgt_lagrange

Vous pouvez également sérialiser votre objet en JSON et le désérialiser dans un objet JavaScript classique tel que

this.collection.doc(sponsor.id).set(JSON.parse( JSON.stringify(sponsor)));

fonctionne en imbrication profonde.

6
Peter

Merci à Fabian Wiles - Je l'ai!

alors que firebase pouvait envoyer les données de votre objet à la base de données, il ne peut pas les instancier dans une instance de votre classe lorsque les données sont renvoyées. Donc les cours sont interdits

il suffit de sauvegarder un objet comme celui-ci:

interface Person{
  name: string;
  age: number
}

var person: Person = { name: 'Toxicable', age: 22} ;
3
Coach

Pour ma solution, j'avais une Interface

export interface Launch {
 id: string;
 date: Date;
 value: number;

}

const project = {} as Launch;

this.db.collection ('launches'). add (projet);

2
Andre Evangelista

C'est un comportement vraiment étrange de la base de feu. Et c'est comme ça que j'ai résolu le problème - en créant une nouvelle interface et en ajoutant une méthode de conversion à ma classe:

export class Happening {
 constructor(
  public date: EventDate,
  public participants: Array<string>,
  public title: string,
  public text: string,
  public uid?: string,
  public id?: string
 ){}

 public toDto = (): HappeningDto => {
  return {
    date: {
      year: this.date.year,
      month: this.date.month,
      day: this.date.day
    },
    participants: this.participants ? this.participants : [],
    title: this.title,
    text: this.text ? this.text : '',
    uid: this.uid,
    id: this.id ? this.id : null
  }
 }
}

export interface HappeningDto {
 date: {
  year: number,
  month: number,
  day: number
 },
 participants: Array<string>,
 title: string,
 text: string,
 uid?: string,
 id?: string
}

Maintenant je peux faire 

add(event: Happening){
  event.uid = this.uid;
  this.$afs.collection<HappeningDto>('events').add(event.toDto())
    .then(
      (success) => console.log(success),
      (err) => console.warn(err)
    )
}
1
Anton Pegov

Firestore ne supporte pas cela. Mais vous pouvez utiliser https://github.com/typestack/class-transformer Cela fonctionne parfaitement pour nous. 

1

Si vous utilisez AngularFire2 et AngularFire2, vous pouvez utiliser AngularFirestype . Ce module est destiné à remplacer AngularFirestore et permet d’obtenir et de définir des données dans Firestore directement avec des objets personnalisés.

Pour ce faire, 3 étapes sont nécessaires: 

1. Installer le type de feu angulaire

`npm install angular-firestype --save`

2. Initialiser le module AngularFirestype avec un objet de mappage

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AngularFirestypeModule, ModelType } from 'angular-firestype';
import { environment } from '../environments/environment';

import { User } from './user.ts';
import { Address } from './address.ts';
import { Message } from './message.ts';

/**
 * Definition of the app model mapping.
 * For more information, see https://github.com/bricepepin/angular-firestype#mapping-object.
 */
const model: {[key: string]: ModelType<any>} = {
  users: {
    type: User,
    arguments: ['username', 'image'],
    structure: {
      adress: Address
    },
    subcollections: {
      messages: Message
    }
  }
};

@NgModule({
 imports: [
   AngularFireModule.initializeApp(environment.firebase),
   AngularFireAuthModule,
   AngularFirestypeModule.forRoot(model),   // Import module using forRoot() to add mapping information
 ],
 declarations: [ AppComponent ],
 bootstrap: [ AppComponent ]
})
export class AppModule {}

3. Injecter le service AngularFirestype

import { Component } from '@angular/core';
import { AngularFirestype, Collection, Document } from 'angular-firestype';

import { User } from './user.ts';

@Component({
 selector: 'app-root',
 templateUrl: 'app.component.html',
 styleUrls: ['app.component.css']
})
export class AppComponent {
   const users: Observable<User[]>;
   const user: User;

   constructor(db: AngularFirestype) {
       const usersCollection: Collection<User> = db.collection<User>('users');
       usersCollection.valueChanges().subscribe(users => this.users = users);

       const userDoc: Document<User> = usersCollection.doc('user1');
       userDoc.valueChanges().subscribe(user => this.user = user);
       userDoc.set(this.user);
   }
}

Vous pouvez utiliser fondamentalement AngularFirestype comme vous utilisiez Angularfirestore.
Pour plus de détails, consultez la page d’accueil ici: https://github.com/bricepepin/angular-firestype .

0
Kheldar