Это продолжение вопроса, который я недавно задал относительно передачи входных данных из модального c ioni. Я устранил первую ошибку, но вторую ошибку мне труднее понять.
Я пытаюсь создать новый экземпляр рабочей области. Это делается с помощью ngFor
из рабочей области в базе данных firebase. Есть две страницы: страница workspace
и страница workspace modal
, первая из которых является родительской.
При нажатии кнопки модальное окно предлагает пользователю ввести заголовок для новой рабочей области ( есть и другие поля, но я просто пытаюсь заставить работать первое). Затем эти данные передаются обратно в домашний компонент, где функция вызывает специальный метод службы, который отправляет их в серверную часть firebase.
Вот HTML и TS для родительского компонента:
<div class="workspaceGrid" style="padding-right: 30px;">
<!-- [workspace]="workspace" passes the data down to the child component via an input property *ngFor="let workspace of workspaces" -->
<app-workspace
*ngFor="let workspace of workspaces"
[workspace]="workspace"
></app-workspace>
<ion-button (click)="openWorkspaceModal()">
Open Modal
</ion-button>
</div>
import { Component, OnInit, OnDestroy } from "@angular/core";
import { Workspace } from "../models/workspace.model";
import { Subscription } from "rxjs";
import { WorkspaceService } from "src/app/services/workspace.service";
// ADD THE MODAL
import { ModalController } from "@ionic/angular";
import { WorkspaceModalComponent } from "../modals/workspace-modal.component";
@Component({
selector: "app-workspaces",
templateUrl: "./workspaces.component.html",
styleUrls: ["./workspaces.component.scss"],
})
export class WorkspacesComponent implements OnInit, OnDestroy {
// HANDLE WORKSPACE SUBSCRIPTION
workspaces: Workspace[];
sub: Subscription;
constructor(
public workspaceService: WorkspaceService,
public modalController: ModalController
) {}
// GET ALL WORKSPACES AND POPULATE THE WORKSPACES ARRAY
ngOnInit() {
this.sub = this.workspaceService
.getUserWorkspaces()
.subscribe((workspaces) => {
this.workspaces = workspaces;
});
}
/**
* PRESENT THE MODAL FOR CREATING A NEW WORKSPACE
* RETURN OF AN ASYNC FUNCTION HAS TO BE A PROMISE
*/
async openWorkspaceModal() {
const workspaceListModal = await this.modalController.create({
component: WorkspaceModalComponent,
// because this is a new workspace, there is no data being passed to the modal component
componentProps: {},
});
workspaceListModal.onDidDismiss().then((result) => {
if (result) {
this.workspaceService.createWorkspace({
title: result,
});
}
});
return await workspaceListModal.present();
}
// NAVIGATE AWAY FROM THE PAGE, WE CAN UNSUBSCRIBE FROM THE WORKSPACES OBSERVABLE
ngOnDestroy() {
this.sub.unsubscribe();
}
}
Вот HTML и TS для модального:
<ion-header color="primary" mode="ios">
<ion-toolbar>
<ion-title>New Workspace</ion-title>
<ion-buttons slot="end">
<ion-button (click)="closeWorkspaceModal()">
<ion-icon slot="icon-only" name="close"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-input
placeholder="Enter a title for the workspace"
[(ngModel)]="data.title"
>
</ion-input>
</ion-item>
<!-- HANDLE SUBMISSION OF THE CONTENT -->
<ion-button [data]="data.title" (click)="closeWorkspaceModal()"
>Create Workspace</ion-button
>
</ion-content>
import { Component, Inject } from "@angular/core";
import { ModalController } from "@ionic/angular";
import { WorkspacesComponent } from "../workspaces/workspaces.component";
import { Workspace } from "../models/workspace.model";
@Component({
selector: "app-workspace-modal",
templateUrl: "./workspace-modal.component.html",
styles: [],
})
export class WorkspaceModalComponent {
public data: Workspace = {
title: "",
description: "",
};
constructor(public modalController: ModalController) {}
/**
* CLOSE THE MODAL ON CLICK
*/
async closeWorkspaceModal() {
await this.modalController.dismiss();
}
}
Вот интерфейс TS, за которым следует функция в службе в бэкэнде, которая создает новое рабочее пространство:
export interface Workspace {
id?: any;
title?: string;
description?: string;
color?: "blue" | "red" | "yellow";
priority?: number;
}
import { Injectable } from "@angular/core";
import { AngularFireAuth } from "@angular/fire/auth";
import { AngularFirestore } from "@angular/fire/firestore";
import * as firebase from "firebase/app";
import { switchMap, map } from "rxjs/operators";
import { Workspace } from "../home/models/workspace.model";
@Injectable({
providedIn: "root",
})
export class WorkspaceService {
constructor(private afAuth: AngularFireAuth, private db: AngularFirestore) {}
/**
*
* @param data
* CREATES A WORKSPACE IN THE DATABASE BASED ON THE CURRENTLY LOGGED IN USER
*/
async createWorkspace(data: Workspace) {
const user = await this.afAuth.currentUser;
return this.db.collection("workspaces").add({
...data,
// automatically sets the UID property of the workspace here
uid: user.uid,
});
}
}
Вот ошибка, которую выдает мне консоль:
ERROR Error: Uncaught (in promise): FirebaseError: [code=invalid-argument]: Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field title.data)
FirebaseError: Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field title.data)
at new n (index.cjs.js:160)
at t.Tc (index.cjs.js:9425)
at index.cjs.js:9624
at zr (index.cjs.js:9625)
at index.cjs.js:9634
at I (index.cjs.js:548)
at Gr (index.cjs.js:9633)
at zr (index.cjs.js:9535)
at index.cjs.js:9634
at I (index.cjs.js:548)
at resolvePromise (zone-evergreen.js:798)
at zone-evergreen.js:705
at fulfilled (tslib.es6.js:71)
at ZoneDelegate.invoke (zone-evergreen.js:364)
at Object.onInvoke (core.js:41654)
at ZoneDelegate.invoke (zone-evergreen.js:363)
at Zone.run (zone-evergreen.js:123)
at zone-evergreen.js:857
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Object.onInvokeTask (core.js:41632)
My gr asp on promises растет, но они недостаточно зрелый, чтобы отлаживать то, что здесь происходит. Я чувствую, что это как-то связано с тем, что интерфейс проходит через все. Единственная причина, по которой я инициировал это в модальном ts, это то, что angular расстроился, сказав, что data.title
не определено, поэтому я сразу же установил его в "". Я думал, что передачи пустого объекта componentProps будет достаточно, но, видимо, этого не произошло.
Большое спасибо за любую помощь!
*** есть некоторый закомментированный код, который не используется .