我是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)
相同谢谢!
答案 0 :(得分:1)
根据您发布的“准则”,我发现了两个可能导致该问题的原因,
创建设置组件时,将调用该构造函数,但是如果您依赖于子组件操作中的属性或数据,就像导航到“设置”页面一样,那么将构造函数移动到任何生命周期钩子
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 });
}
}