Angular 10 / Ioni c 5 - Передача входных данных из модального окна в родительский компонент с последующей отправкой в ​​базу данных firebase - PullRequest
0 голосов
/ 13 июля 2020

Это продолжение вопроса, который я недавно задал относительно передачи входных данных из модального 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 будет достаточно, но, видимо, этого не произошло.

Большое спасибо за любую помощь!

*** есть некоторый закомментированный код, который не используется .

Ответы [ 2 ]

1 голос
/ 13 июля 2020

Я думаю, проблема в том, что форма данных, полученных вами из вашего модального окна через onDidDismiss, здесь:

    workspaceListModal.onDidDismiss().then((result) => {
      if (result) {
        this.workspaceService.createWorkspace({
          title: result,
        });
      }
    });

Результаты в искаженном объекте Workspace:

{
     title: {
         data: undefined
         role: undefined
     }
}

Что вы пытаются перейти в Firestore (следовательно, ошибка, связанная с тем, что title.data не определена, так как внутри вы отклонили модальное окно без аргументов).

Чтобы исправить это, вам нужно убедиться, что модальное окно отклоняется, а что затем формируется внутри Метод onDidDismiss является допустимым объектом формы рабочей области:

Во-первых, внутри вашего WorkspaceModalComponent убедитесь, что вы отклоняете (закрываете) модальное окно, включая ваш объект данных:

  async closeWorkspaceModal() {
    await this.modalController.dismiss(this.data);
  }

Теперь внутри метода onDidDismiss результат ' 'будет иметь форму:

{
    data: this.data, // which is your data object
    role: undefined
}

Поэтому вам нужно убедиться, что вы это делаете:

workspaceListModal.onDidDismiss().then((result) => {
  if (result && result.data) {
    this.workspaceService.createWorkspace(result.data);
  }
});

Если вы console.log (result.data), он должен иметь правильную форму рабочей области. и ошибка должна быть устранена.

1 голос
/ 13 июля 2020

Если вы зарегистрируете, что такое data, которое вы передаете на createWorkspace, я готов держать пари, что это не определено. Вы не возвращаете ничего из своего модального окна в его отклонении.

См. Документацию для ion-modal: https://ionicframework.com/docs/api/modal#dismissing -a-modal

Your closeWorkspaceModal метод должен передать this.data в модальное отклонение.

async closeWorkspaceModal() {
    await this.modalController.dismiss(this.data);
  }
...