在 Nativescript Angular 应用程序中,我使用带有延迟加载的 Nativescript Material Design 选项卡。
我有一个 ReportsComponent,显示费用报告的 RadListView,每个报告都包含一个或多个费用项目。
在单独的 ExpenseComponent 中,我有一个表单,允许用户创建费用项目并将其添加到现有报告或创建新报告。
当用户执行此操作并单击返回“报告”页面时,如何向他们显示反映他们所做添加的刷新列表?
ReportsComponent 中的 ngOnInit 调用 getReports 函数,但它仅在用户登录时(加载选项卡时)触发一次。
选项卡模块 tabs.module.ts 有这个
@NgModule({
imports: [
NativeScriptCommonModule,
NativeScriptRouterModule,
NativeScriptRouterModule.forChild([
{
path: "default", component: TabsComponent, children: [
{
path: "home",
outlet: "homeTab",
component: NSEmptyOutletComponent,
loadChildren: () => import("~/home/home.module").then(m => m.HomeModule),
},
{
path: "expense",
outlet: "expenseTab",
component: NSEmptyOutletComponent,
loadChildren: () => import("~/expense/expense.module").then(m => m.ExpenseModule),
},
{
path: "journey",
outlet: "journeyTab",
component: NSEmptyOutletComponent,
loadChildren: () => import("~/journey/journey.module").then(m => m.JourneyModule),
},
{
path: "reports",
outlet: "reportsTab",
component: NSEmptyOutletComponent,
loadChildren: () => import("~/reports/reports.module").then(m => m.ReportsModule),
}
]
}
])
],
declarations: [
TabsComponent
],
providers: [],
schemas: [NO_ERRORS_SCHEMA]
})
reports.component.ts
ngOnInit() {
this.getReports();
}
public getReports() {
console.log("In getReports");
this.updateService.getReports()
.subscribe({
next: (data) => {
this._reports = new ObservableArray<Report>();
this._tempreports = new ObservableArray<Report>();
if (data["reports"] == "No Reports") {
console.log("No Reports");
} else {
for (let i = 0; i < (<any>data).reportid.length; i++) {
// load up reports
this._tempreportnames.push(new Report(
(<any>data).reportid[i],
(<any>data).report_code[i],
(<any>data).report_name[i],
(<any>data).report_status[i],
(<any>data).report_value[i],
(<any>data).report_type[i],
(<any>data).report_justification,
(<any>data).total_business,
(<any>data).total_private));
}
this._reports = this._tempreports;
console.log("getReports this._reports="+JSON.stringify(this._reports));
}
},
error: (error) => {
console.log("Problems...");
}
});
}
public get reports(): ObservableArray<Report> {
return this._reports;
}
在 reports.component.html 中我有
<RadListView
[items]="reports"
selectionBehavior="Press"
>
<ng-template tkListItemTemplate let-item="item">
etc
报告列表在启动时加载良好。
但是当我转到 ExpenseComponent 表单并创建费用并将其添加到新报告中,然后返回到报告列表时,它尚未更新。
我该如何实现这一点?
如果我需要数据绑定,我应该如何处理?
我想,我只需要在每次访问该页面时调用 getReports() 即可。
谢谢。
======================================== 更新(还是不行)
我一直在用 ChatGPT 来解决这个问题,并尝试通过多种方法手动强制进行更改检测:ChangeDetectorRef、ChangeDetectionStrategy OnPush 和 ApplicationRef.tick。没有任何方法可以更新 ReportsComponent 视图以显示在其他地方新创建的报表。在不同的 ExpenseComponent 上提交表单后,会在后端创建报告。发生这种情况时,我只想从服务器 http GET 报告列表并刷新 ReportsComponent 视图。
这里有一些代码(它是 ChangeDetectorRef 和 ApplicationRef.tick 的混合体,所以有点混乱,但似乎没有任何东西可以更新视图强调的文本。我看不到是什么错了。)
在 ExpenseComponent 中成功创建费用并附加到新报告后,我们有:
onExpenseSuccess(data: any) {
console.log('Expense successfully created, refreshing reports.');
// Trigger a refresh of the reports list
this.updateService.refreshReports();
在 UpdateService 中我们有:
private reportCreateSource = new Subject<Report>();
reportCreate$ = this.reportCreateSource.asObservable();
private reportRefreshSource = new Subject<void>();
reportRefresh$ = this.reportRefreshSource.asObservable();
...
getReports() {
let url = Config.apiUrl + "ns_get_reports.php";
return this.http.get<any>(url).pipe(
map(data => {
if (!data || !data.reportid || !Array.isArray(data.reportid)) {
throw new Error('Invalid data structure');
}
return data.reportid.map((id, i) => {
let status_codes = this.displayReportStatus(data.report_status[i]);
let status_text = status_codes[0];
let status_class = status_codes[1];
let disp_report_value = this.funcService.moneyFormat(Number(data.report_value[i]));
return new Report(
id,
data.report_code[i] || '',
data.report_name[i] || '',
data.report_status[i] || '0',
data.report_value[i] || '0.00',
disp_report_value,
data.report_type[i] || 'report',
status_text,
status_class,
data.report_justification ? data.report_justification[i] : '',
data.total_business ? data.total_business[i] : '',
data.total_private ? data.total_private[i] : ''
);
});
}),
catchError(this.handleErrors)
);
}
refreshReports() {
console.log("UpdateService - Refreshing Reports");
this.reportRefreshSource.next();
}
在 ReportsComponent 构造函数中是订阅
import {Component, OnInit, Injectable, OnDestroy, ApplicationRef, ChangeDetectorRef, ChangeDetectionStrategy } from "@angular/core";
...
@Component({
selector: "Reports",
providers: [UpdateService],
templateUrl: "./reports.component.html",
styleUrls: ["./reports.component.css"],
changeDetection: ChangeDetectionStrategy.OnPush
})
@Injectable()
export class ReportsComponent implements OnInit, OnDestroy {
private _reports: ObservableArray<Report> = new ObservableArray<Report>();
private _expenses: ObservableArray<Expense>;
private subscriptions: Subscription[] = [];
_reportsList: Report[] = [];
header: string;
isLoading = false;
disp_report_value: string;
subscription: Subscription;
constructor(
...
private cdr: ChangeDetectorRef,
private appRef: ApplicationRef
) {
this.subscriptions.push(
this.updateService.reportCreate$.subscribe((report: Report) => {
this.cdr.markForCheck();
console.log("Adding new report: ", report);
this.addReport(report);
this.cdr.detectChanges();
this.appRef.tick ();
console.log('Change detection triggered: this.updateService.reportCreate$');
})
);
this.subscriptions.push(
this.updateService.reportRefresh$.subscribe(() => {
this.cdr.markForCheck();
console.log("Refreshing reports list");
this.getReports();
this.cdr.detectChanges();
this.appRef.tick ();
console.log('Change detection triggered: this.updateService.reportRefresh$');
})
);
}
...
ngOnInit() {
console.log('ReportsComponent initialized');
this.getReports();
}
ngOnDestroy(): void {
// Unsubscribe to avoid memory leaks
this.subscriptions.forEach(sub => sub.unsubscribe());
}
// Reports getter
get reports(): ObservableArray<Report> {
return this._reports;
}
addReport(report: Report) {
this._reports.push(report);
console.log('Report added to list:', report);
this._reports = new ObservableArray([...this._reports]);
this.cdr.detectChanges();
this.appRef.tick ();
}
getReports() {
console.log("In getReports");
this.updateService.getReports().subscribe({
next: (data: Report[]) => {
console.log('Fetched data in getReports:', data);
if (!Array.isArray(data) || data.length === 0) {
console.log("No reports to show or data is not in expected format");
return;
}
this._reports = new ObservableArray(data);
console.log('Updated reports:', this._reports);
this.cdr.detectChanges();
this.appRef.tick ();
},
error: (error) => {
console.log("Problems...", this.formatError(error));
this.cdr.detectChanges();
}
});
}
在 ReportsComponent 视图中我们有一个 RadListView
<RadListView [items]="reports" selectionBehavior="Press">
非常感谢一些指导! TIA
例如,您可以在
Subject<Report>
中创建 UpdateService
,然后订阅它以进行通话 GetReports()
。
更新服务.service.ts
reportCreate$: Subject<Report> = new Subject<Report>();
reports.component.ts
constructor(private updateService: UpdateService){
this.updateService.reportCreate$.subscribe(reult => this.GetReports())}
创建报告.component.ts
createReportFunction(){
this.updateService.reportCreate$.next(report)