离开页面时,ngFor循环内容消失

时间:2018-01-13 02:45:22

标签: javascript angular ionic-framework ionic3

我是Angular和Ionic的新手。我正在遍历存储在我的Firestore数据库中的一系列内容。当应用程序重新编译并加载时,我转到设置页面(这就是循环发生的地方),我看到内容数组就好了。我可以在Firestore上更新它,它会在应用程序中实时更新。这一切都很好。但如果我点击“返回”(因为正在使用“navPush”访问设置),然后再次单击“设置”页面,整个循环内容将消失。

东西仍在数据库中就好了。我必须重新编译项目以使内容再次出现。但是,一旦我离开该设置页面,然后回来,内容就会消失。

这是我的代码:

HTML设置页面(循环的主要代码):

<ion-list>
    <ion-item *ngFor="let setting of settings">
        <ion-icon item-start color="light-grey" name="archive"></ion-icon>
        <ion-label>{{ setting.name }}</ion-label>
      <ion-toggle (ionChange)="onToggle($event, setting)" [checked]="setting.state"></ion-toggle>
    </ion-item>
</ion-list>

该设置页面TS文件:

import { Settings } from './../../../models/settings';
import { DashboardSettingsService } from './../../../services/settings';
import { Component, OnInit } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-dashboard-settings',
  templateUrl: 'dashboard-settings.html',
})
export class DashboardSettingsPage implements OnInit {


  settings: Settings[];
  checkStateToggle: boolean;
  checkedSetting: Settings;

  constructor(public dashboardSettingsService: DashboardSettingsService) {
    this.dashboardSettingsService.getSettings().subscribe(setting => {
      this.settings = setting;
      console.log(setting.state);
    })
  }

  onToggle(event, setting: Settings) {
    this.dashboardSettingsService.setBackground(setting);
  }

}

我的设置服务文件(DashboardSettingsService导入):

import { Settings } from './../models/settings';
import { Injectable, OnInit } from '@angular/core';
import * as firebase from 'firebase/app';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Observable';

@Injectable()

export class DashboardSettingsService implements OnInit {

  settings: Observable<Settings[]>;
  settingsCollection: AngularFirestoreCollection<Settings>;
  settingDoc: AngularFirestoreDocument<Settings>;

    public checkedSetting = false;

  setBackground(setting: Settings) {
    if (this.checkedSetting == true) {
      this.checkedSetting = false;
    } else if(this.checkedSetting == false) {
      this.checkedSetting = true;
    };
    this.settingDoc = this.afs.doc(`settings/${setting.id}`);
    this.settingDoc.update({state: this.checkedSetting});
    console.log(setting);
  }

  constructor(private afAuth: AngularFireAuth,private afs: AngularFirestore) {
    this.settingsCollection = this.afs.collection('settings');
    this.settings = this.settingsCollection.snapshotChanges().map(changes => {
      return changes.map(a => {
        const data = a.payload.doc.data() as Settings;
        data.id = a.payload.doc.id;
        return data;
      });
  });

}
isChecked() {
  return this.checkedSetting;
}

    getSettings() {
      return this.settings;
    }

    updateSetting(setting: Settings) {
      this.settingDoc = this.afs.doc(`settings/${setting.id}`);
      this.settingDoc.update({ state: checkedSetting });
    }

}

知道是什么造成的吗? 我的循环之前在自定义组件中,所以我尝试将其直接放在仪表板设置页面中,但它仍然无法正常工作。我不知道该在这里查看什么。我试着把:

this.dashboardSettingsService.getSettings().subscribe(setting => {
  this.settings = setting;
})

...改为使用ngOninit方法,甚至是ionViewWillLoad和其他方法,但它也不起作用。

我正在使用Ionic最新版本(3+)和Angular(5)

相同

谢谢!

2 个答案:

答案 0 :(得分:1)

根据您发布的“准则”,我发现了两个可能导致该问题的原因,

  1. 在构造函数中调用Service方法:
  2. 创建设置组件时,将调用该构造函数,但是如果您依赖于子组件操作中的属性或数据,就像导航到“设置”页面一样,那么将构造函数移动到任何生命周期钩子

      ngAfterContentInit() {
        // Component content has been initialized
      }
      ngAfterContentChecked() {
        // Component content has been Checked
      }
      ngAfterViewInit() {
        // Component views are initialized
      }
      ngAfterViewChecked() {
        // Component views have been checked
      }
    

    即使您在生命周期事件中添加了服务调用方法,但只有在您在Settings服务文件的构造函数中订阅服务方法时才会调用它。所以只需尝试按如下方式更改服务文件:

    getSettings() {
         this.settingsCollection = this.afs.collection('settings');
         this.settingsCollection.snapshotChanges().map(changes => {
          return changes.map(a => {
            const data = a.payload.doc.data() as Settings;
            data.id = a.payload.doc.id;
            return data;
          });
      });
    
    
        }
    

    更新:

    尝试更改Getsettings,如下所示,请使用最新更改更新您的问题

    getSettings() {
    
    
       this.settingsCollection = this.afs.collection('settings');
     return this.settingsCollection.snapshotChanges().map(changes => {
          return changes.map(a => {
            const data = a.payload.doc.data() as Settings;
            data.id = a.payload.doc.id;
            return data;
          });
      });
    
    
        }
    

答案 1 :(得分:0)

我不确定,但我怀疑订阅可观察设置settings: Observable<Settings[]>可能是罪魁祸首。这可能适用于第一次加载,因为正在创建和注入DashboardSettingsService,因此加载设置,然后发出项目(导致DashboardSettingsPage中的订阅事件触发)。

在第二页加载时,DashboardSettingsService已经存在(默认情况下服务创建为单例) - 这意味着不会调用构造函数(这是您设置observable的地方),因此它不会为您的组件发出新的设置对象。

因为Observable不会发出任何内容,所以不会触发以下事件,这意味着永远不会填充本地设置对象:

this.dashboardSettingsService.getSettings().subscribe(setting => { this.settings = setting; console.log(setting.state); })

您可以使用提供最新(缓存)设置对象的方法或新Observable(不要忘记取消订阅!!)来重构您的服务,而不是创建一个只能通过创建或更改来触发的Observable底层存储对象。

这是一个不会改变方法签名的简单示例。

import { Settings } from './../models/settings';
import { Injectable, OnInit } from '@angular/core';
import * as firebase from 'firebase/app';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

@Injectable()

export class DashboardSettingsService implements OnInit {

  settings: Observable<Settings[]>;
  cachedSettings: Settings[];
  settingsCollection: AngularFirestoreCollection<Settings>;
  settingDoc: AngularFirestoreDocument<Settings>;

  public checkedSetting = false;

  setBackground(setting: Settings) {
    if (this.checkedSetting == true) {
      this.checkedSetting = false;
    } else if(this.checkedSetting == false) {
      this.checkedSetting = true;
    };
    this.settingDoc = this.afs.doc(`settings/${setting.id}`);
    this.settingDoc.update({state: this.checkedSetting});
    console.log(setting);
  }

  constructor(private afAuth: AngularFireAuth,private afs: AngularFirestore) {
    this.settingsCollection = this.afs.collection('settings');
    this.settings = this.settingsCollection.snapshotChanges().map(changes => {
        return changes.map(a => {
          const data = a.payload.doc.data() as Settings;
          data.id = a.payload.doc.id;
          this.cachedSettings = data;
          return data;
        });
     }); 
   }

  isChecked() {
    return this.checkedSetting;
  }

  getSettings() {
    return Observable.of(this.cachedSettings);
  }

  updateSetting(setting: Settings) {
    this.settingDoc = this.afs.doc(`settings/${setting.id}`);
    this.settingDoc.update({ state: checkedSetting });
  }     
}