Nativescript 角度选项卡。更改另一个组件中的数据后更新组件的视图

问题描述 投票:0回答:1

在 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

angular nativescript nativescript-angular
1个回答
1
投票

例如,您可以在

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)
© www.soinside.com 2019 - 2024. All rights reserved.