【问题标题】:Ionic open a Popover from another component within a pageIonic 从页面中的另一个组件打开一个 Popover
【发布时间】:2021-09-25 05:19:42
【问题描述】:

我知道这里已经存在这个问题:Ionic open Popover from another component 但我没有得到解决方案。

我有一个页面,其中包含一个带有按钮的工具栏组件。此按钮应触发页面内的功能。当我从页面内部触发该功能时,它可以工作。我还可以看到 onInit 填充了popoverController,但是稍后执行该函数时它是未定义的。

ERROR TypeError: Cannot read property 'create' of undefined
at HeaderComponent.push.6176.LocationSelectionPage.openAddLocation (location-selection.page.ts:92)
at HeaderComponent_ion_buttons_7_Template_ion_buttons_click_0_listener (template.html:14)
at executeListenerWithErrorHandling (core.js:15285)
at wrapListenerIn_markDirtyAndPreventDefault (core.js:15323)
at HTMLElement.<anonymous> (platform-browser.js:560)
at ZoneDelegate.invokeTask (zone.js:406)
at Object.onInvokeTask (core.js:28664)
at ZoneDelegate.invokeTask (zone.js:405)
at Zone.runTask (zone.js:178)
at ZoneTask.invokeTask [as invoke] (zone.js:487)

函数如下所示:

openAddLocation() {
this.popover
  .create({
    component: LocationAddPage,
    cssClass: '',
    showBackdrop: true,
  })
  .then((popoverElement) => {
    popoverElement.present();
  });

}

我有另一个可以正常工作的弹出窗口,但它是在同一页面中触发的。

header.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
})
export class HeaderComponent implements OnInit {
  @Input() title: string;
  @Input() openAddLocation: Function;
  showBackBtn: boolean = false;
  showMenuBtn: boolean = true;
  path: string;

  constructor(private router: Router) {}

  ngOnInit() {
    this.path = this.router.url;
    if (/labsite-selection|retailers|location-selection/.test(this.path)) {
      this.showBackBtn = true;
      this.showMenuBtn = false;
    } else {
      this.showBackBtn = false;
      this.showMenuBtn = true;
    }
  }
}

components.module.ts

import { NgModule } from '@angular/core';
import { IonicModule } from '@ionic/angular';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HeaderComponent } from './header/header.component';
import { SearchComponent } from './search/search.component';

@NgModule({
  imports: [IonicModule, CommonModule, FormsModule],
  declarations: [HeaderComponent, SearchComponent],
  exports: [HeaderComponent, SearchComponent],
  providers: [],
})
export class ComponentsModule {}

header.component.html

<ion-header mode="md">
  <ion-toolbar color="primary">
    <ion-title>{{ title }}</ion-title>
    <ion-buttons slot="start">
      <ion-menu-button *ngIf="showMenuBtn" autoHide="false"></ion-menu-button>
      <ion-back-button
        *ngIf="showBackBtn"
        defaultHref="start"
      ></ion-back-button>
    </ion-buttons>
    <ion-buttons
      *ngIf="path.includes('location-selection')"
      slot="end"
      (click)="openAddLocation()"
    >
      <ion-button>
        <ion-icon slot="icon-only" name="add-outline"></ion-icon>
      </ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

【问题讨论】:

  • 使用Observables
  • 你应该为你在哪里使用它的每个组件注册你的popover
  • @Danil 我在页面模块和组件模块(所有组件都注册的地方)以及c的弹出页面本身中注册了弹出框
  • @kdc 你能添加产生错误的组件代码(带有导入和声明)吗?
  • @DanilProkhorenko 完成

标签: angular ionic-framework ionic5


【解决方案1】:

首先,解决方案。您以这种方式使用 app-header 组件:

<app-header [openAddLocation]="openAddLocation"></app-header>

你的页面中有这段代码:

openAddLocation() {
    this.popover.create({
        component: LocationAddPage,
        cssClass: '',
        showBackdrop: true,
    }).then((popoverElement) => {
        popoverElement.present();
    });
}

你应该把它改成这样:

openAddLocation = () => {
    this.popover.create({
        component: LocationAddPage,
        cssClass: '',
        showBackdrop: true,
    }).then((popoverElement) => {
        popoverElement.present();
    });
}

说明:

在第一种情况下,您传递了Function。此方法不会将this 上下文传递给组件。当组件尝试调用@Input函数时,它调用的是组件的this,而不是页面的this

在第二种情况下,您传递了一个闭包。这里将在两个调用中使用页面的this

另一种解决方案

我认为第一个解决方案对您来说很容易实施,但我认为这不是一个好方法。我认为使用@Output params而不是@Input来调用函数会更好。

在你的header.component.ts:

- import { Component, Input, OnInit } from '@angular/core';
+ import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core';

- @Input() openAddLocation: Function;
+ @Output() openAddLocation: EventEmitter<void> = new EventEmitter();

header.component.html:

- (click)="openAddLocation()"
+ (click)="openAddLocation.emit()"

那么你可以这样在你的页面上使用它:

<app-header (openAddLocation)="openAddLocation()"></app-header>

有关 @Input@Output 文档中参数的更多信息:https://angular.io/guide/inputs-outputs

【讨论】:

  • 感谢您的帮助。非常感谢。
猜你喜欢
  • 2020-05-12
  • 2018-11-08
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
  • 2014-04-07
相关资源
最近更新 更多