在2个组件之间共享来自服务器的JSON数据 [英] Sharing JSON data from server between 2 components

查看:45
本文介绍了在2个组件之间共享来自服务器的JSON数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我昨天发布了这篇文章,但是今天我已经更改了很多代码,所以我基本上已经重写了我的问题:

我最初使用TabView模板使用NativeScript with Angular应用程序,并且使用选项卡上方的模式窗口使用登录表单,这似乎可以正常工作-登录表单没有选项卡,并且登录后被带到TabView

成功登录后,我想在选项卡式组件中调用方法,并使用已登录用户的特定内容更新各自的模板.

例如,其中之一是用户报告列表.

我试图通过从login.component.ts中的成功处理程序调用服务,然后在reports.component.ts中访问此服务,来从服务器中获取用户报告列表,并在reports.component.html中显示该列表. /p>

在login.component.ts中,我位于顶部

    ...
import { User } from "../shared/user/user.model";
import { UserService } from "../shared/user/user.service";
import { ReportsComponent } from "../reports/reports.component";
import { UpdateService } from "../shared/update.service";
...

...
@Component({
    selector: 'login',
    moduleId: module.id,    
    providers: [UserService, ReportsComponent, ReportService, UpdateService ],
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.css']
})
...

在构造函数中,我有

private userService: UserService,
private repts: ReportsComponent,
private reportService: ReportService, 
private updateService: UpdateService,

那我有

public login() {

   this.userService.login(this.user)
   .subscribe(
        (data) => {              
            //console.log("login data in component = "+JSON.stringify(data));  


            if (data.authenticated==false) {
                ApplicationSettings.setBoolean("authenticated", false);
                alert("Unfortunately we could not log you in: "+data.message);
            } else if (data.authenticated==true) {
                ApplicationSettings.setBoolean("authenticated", true);
                ApplicationSettings.setString("token", data.token);

                console.log("authenticated="+ApplicationSettings.getBoolean("authenticated"));
                console.log("Login success! token="+data.token);

                console.log("calling updateReports from update.service.ts");

                this.updateReports();       

                //this.expense.populate_reports(this.expense); 
                //this.expense.populate_categories(this.expense); 

                this.modalDialogParams.closeCallback(() => console.log('Login modal closed'));

            }

        },
        (error) => alert("Unfortunately we could not log you in.")
   );        
}    
public updateReports() {
    this.updateService.getReports()
    .subscribe(
        (data) => {              
            //console.log("report data in login component = "+JSON.stringify(data));  
        },
        (error) => alert("Problems...")
   );         
}

在我拥有的update.service.ts中

@Injectable()
export class UpdateService {

private _expenses: ObservableArray<Expense>;

private reportDataSource = new Subject<string>(); // Source
reportData$ = this.reportDataSource.asObservable(); // Stream

constructor(private http: Http) { }


getReports() {
    console.log("in updateService getReports");

    let url = Config.apiUrl + "ns_get_reports.php";
    //console.log(url);
    return this.http.get(
        url,
        { headers: this.getCommonHeaders() }
    ).pipe(
        map(this.extractData),
        tap(data => {
            //alert("oi");
            this.reportDataSource.next(data);
            //console.log("reports listing in update service = "+JSON.stringify(data));
        }),
        catchError(this.handleErrors)
    );
}       
getCommonHeaders() {
    let headers = new Headers();
    let token=ApplicationSettings.getString("token");        
    headers.append("Content-Type", "application/json");
    headers.append("token", token);
    return headers;
}
handleErrors(error: Response) {
    console.log(JSON.stringify(error.json()));
    return Observable.throw(error);
}
private extractData(res: Response) {
    let body = res.json();
    return body || {};
}    

}

然后在我拥有的report.component.ts中

export class ReportsComponent implements OnInit {

//private report: Report;
private _reports: ObservableArray<Report>;
private _expenses: ObservableArray<Expense>;
header: string;
report_status: Array<String>;

subscription: Subscription;

constructor(private router: Router, 
    private reportService: ReportService, 
    private expenseService: ExpenseService,
    private _changeDetectionRef: ChangeDetectorRef, 
    private updateService: UpdateService) {

    this._reports = new ObservableArray<Report>();
    this.subscription = updateService.reportData$.subscribe(
        (res) => {
            console.log("reports listing in reports component = "+JSON.stringify(res));

            let data=JSON.parse(JSON.stringify(res));

            if (data["reports"]=="No Reports") {                 
                // No reports to show
            } else {  
                var status_text;
                var status_class;
                for (let i = 0; i < data.reportid.length; i++) {
                    var status_codes=this.displayReportStatus(data.report_status[i]);
                    status_text=status_codes[0];
                    status_class=status_codes[1];

                    this._reports.push(new Report(data.reportid[i], data.report_name[i], data.report_status[i], data.report_value[i], status_text, status_class, data.report_justification));
                }
                this._changeDetectionRef.markForCheck();
                if (!this._changeDetectionRef['destroyed']) {
                    this._changeDetectionRef.detectChanges();
                }

            }

        }
    );
}
public get reports(): ObservableArray<Report> {
    return this._reports;
} 

console.log("reports listing in reports component = "+JSON.stringify(data));

正在输出报告数据没有问题,因此服务正在返回正确的数据.

但是,模板未显示格式化的报告列表.它是空白的.模板如下:

   <!--
    <RadListView [items]="reports" (itemTap)="onReportItemTap($event)" >
    //-->
    <RadListView [items]="reports" >
        <ng-template tkListItemTemplate let-item="item">
            <StackLayout class="itemTemplateStackLayout" orientation="vertical">

                    <StackLayout class="reportStackLayout" orientation="vertical">

                        <Label class="labelName blue_text bold_text list-group-item" [nsRouterLink]="['../report', item.reportid]" [text]="item.report_name"></Label>


                        <GridLayout class="reportDetailsGridLayout" columns="*, *">
                            <Label row="0" col="0" horizontalAlignment="left" [class]="item.status_class" class="labelStatus"  [text]="item.status_text" textWrap="true"></Label>
                            <Label row="0" col="1" horizontalAlignment="right" class="labelValue green_text bold_text" [text]="item.report_value" textWrap="true"></Label>
                        </GridLayout>

                    </StackLayout>

            </StackLayout>
        </ng-template>         
    </RadListView>
</GridLayout>

任何想法我在做什么错

希望我已经做了足够的解释-如果需要进一步说明,请告诉我.

谢谢.

10月9日.

这是现在的reports.component.ts.仍然没有更新视图.

import { Component, ChangeDetectorRef, OnInit } from "@angular/core";

import { ReportComponent } from "./report.component";
import { Report } from "../shared/report/report.model";
import { Expense } from "../shared/expense/expense.model";
import { ReportService } from "../shared/report/report.service";
import { ExpenseService } from "../shared/expense/expense.service";
import { UpdateService } from "../shared/update.service";
import { Subject, Subscription } from 'rxjs';
import { ActivatedRoute, Router } from "@angular/router";
import { NativeScriptRouterModule } from "nativescript-angular/router"; 
import { Page } from "tns-core-modules/ui/page";
import { ObservableArray } from "tns-core-modules/data/observable-array";
import { ListViewEventData } from "nativescript-ui-listview";
import { RadListView } from "nativescript-ui-listview";


import { RouterExtensions } from "nativescript-angular/router";
import * as ApplicationSettings from "application-settings";
import {getBoolean, setBoolean, getNumber, setNumber, getString, setString, hasKey, remove, clear} from "tns-core-modules/application-settings";
import { Injectable } from "@angular/core";

declare var module: {
    id: string;
 }
@Component({
selector: "Reports",
moduleId: module.id,
providers: [ReportService, ExpenseService, UpdateService],
templateUrl: "./reports.component.html",
styleUrls: ["./reports.component.css"]
})


export class ReportsComponent implements OnInit {

//private report: Report;
private _reports: ObservableArray<Report>;
private _tempreports: ObservableArray<Report>;
private _expenses: ObservableArray<Expense>;
header: string;
report_status: Array<String>;
isLoading = true;
foo: string;

private listView: RadListView;

subscription: Subscription;

constructor(private router: Router, 
    private route: ActivatedRoute,
    private reportService: ReportService, 
    private expenseService: ExpenseService,
    private _changeDetectionRef: ChangeDetectorRef, 
    private updateService: UpdateService) {

        this.subscription = this.updateService.reportData$.subscribe(
            (res) => {
                console.log("isLoading="+this.isLoading);
                console.log("reports listing in reports component = "+JSON.stringify(res));


                this._reports = new ObservableArray<Report>();
                this._tempreports = new ObservableArray<Report>();

                let data=JSON.parse(JSON.stringify(res));

                if (data["reports"]=="No Reports") {                 
                    // No reports to show
                } else {  
                    var status_text;
                    var status_class;
                    for (let i = 0; i < data.reportid.length; i++) {
                        var status_codes=this.displayReportStatus(data.report_status[i]);
                        status_text=status_codes[0];
                        status_class=status_codes[1];

                        this._tempreports.push(new Report(data.reportid[i], data.report_name[i], data.report_status[i], data.report_value[i], status_text, status_class, data.report_justification));
                    }
                    this._reports = this._tempreports;
                    this._changeDetectionRef.markForCheck();
                    if (!this._changeDetectionRef['destroyed']) {
                        this._changeDetectionRef.detectChanges();
                    }

                    this.isLoading=false;
                    //this.listView.refresh();                      
                    console.log("isLoading="+this.isLoading);   

                }

            }
        );

}
onListLoaded(args) {
    console.log("In onListLoaded");
    this.listView = args.object;
    this.listView.refresh();     
}

public get reports(): ObservableArray<Report> {
    //console.log("Where are the focking reports");
    return this._reports;
} 

解决方案

您正在测试哪个平台(ios/android)? 对于ios,为listview或其父组件提供高度和宽度非常重要.否则,乍一看,您的代码对我来说看起来不错. 您还可以尝试其他几件事进行进一步调试

  1. 订阅(已加载)RadListView的方法.

  2. 尝试在这样加载的状态下分配列表视图

onListLoaded(args){this.listView = args.object;}

,并在获得报告数据后通过this.listview.refresh()刷新列表视图. 3.首先具有一个activityIndi​​cator并隐藏列表.拥有报告后,隐藏指示器,使丢失的内容可见.

<ActivityIndicator [busy]="isLoading" [visibility]="isLoading ? 'visible' : 'collapse'" row="2" horizontalAlignment="center"></ActivityIndicator>

4.将数据推送到临时数组,一旦所有项目都被使用,请将该临时数组分配给报表.

_tempreports.push(new Report(data.reportid[i], data.report_name[i], data.report_status[i], data.report_value[i], status_text, status_class, data.report_justification));
this._reports = _tempreports;

I posted this yesterday but I have changed so much of the code today I have basically re-written my question:

I have a NativeScript with Angular app using the TabView template and a login form using a modal window over the tabs initially and this appears to be working OK - the login form has no tabs and when logged in I am taken to the TabView.

Upon successful login I want to call methods within the tabbed components and update the respective templates with content specific to the logged in user.

For example one of these is a list of user reports.

I am trying to get a list of user reports from our server and display the list in reports.component.html by calling a service from the success handler in login.component.ts then accessing this in reports.component.ts

In login.component.ts I have at the top

    ...
import { User } from "../shared/user/user.model";
import { UserService } from "../shared/user/user.service";
import { ReportsComponent } from "../reports/reports.component";
import { UpdateService } from "../shared/update.service";
...

...
@Component({
    selector: 'login',
    moduleId: module.id,    
    providers: [UserService, ReportsComponent, ReportService, UpdateService ],
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.css']
})
...

In the constructor I have

private userService: UserService,
private repts: ReportsComponent,
private reportService: ReportService, 
private updateService: UpdateService,

Then I have

public login() {

   this.userService.login(this.user)
   .subscribe(
        (data) => {              
            //console.log("login data in component = "+JSON.stringify(data));  


            if (data.authenticated==false) {
                ApplicationSettings.setBoolean("authenticated", false);
                alert("Unfortunately we could not log you in: "+data.message);
            } else if (data.authenticated==true) {
                ApplicationSettings.setBoolean("authenticated", true);
                ApplicationSettings.setString("token", data.token);

                console.log("authenticated="+ApplicationSettings.getBoolean("authenticated"));
                console.log("Login success! token="+data.token);

                console.log("calling updateReports from update.service.ts");

                this.updateReports();       

                //this.expense.populate_reports(this.expense); 
                //this.expense.populate_categories(this.expense); 

                this.modalDialogParams.closeCallback(() => console.log('Login modal closed'));

            }

        },
        (error) => alert("Unfortunately we could not log you in.")
   );        
}    
public updateReports() {
    this.updateService.getReports()
    .subscribe(
        (data) => {              
            //console.log("report data in login component = "+JSON.stringify(data));  
        },
        (error) => alert("Problems...")
   );         
}

In update.service.ts I have

@Injectable()
export class UpdateService {

private _expenses: ObservableArray<Expense>;

private reportDataSource = new Subject<string>(); // Source
reportData$ = this.reportDataSource.asObservable(); // Stream

constructor(private http: Http) { }


getReports() {
    console.log("in updateService getReports");

    let url = Config.apiUrl + "ns_get_reports.php";
    //console.log(url);
    return this.http.get(
        url,
        { headers: this.getCommonHeaders() }
    ).pipe(
        map(this.extractData),
        tap(data => {
            //alert("oi");
            this.reportDataSource.next(data);
            //console.log("reports listing in update service = "+JSON.stringify(data));
        }),
        catchError(this.handleErrors)
    );
}       
getCommonHeaders() {
    let headers = new Headers();
    let token=ApplicationSettings.getString("token");        
    headers.append("Content-Type", "application/json");
    headers.append("token", token);
    return headers;
}
handleErrors(error: Response) {
    console.log(JSON.stringify(error.json()));
    return Observable.throw(error);
}
private extractData(res: Response) {
    let body = res.json();
    return body || {};
}    

}

Then in reports.component.ts I have

export class ReportsComponent implements OnInit {

//private report: Report;
private _reports: ObservableArray<Report>;
private _expenses: ObservableArray<Expense>;
header: string;
report_status: Array<String>;

subscription: Subscription;

constructor(private router: Router, 
    private reportService: ReportService, 
    private expenseService: ExpenseService,
    private _changeDetectionRef: ChangeDetectorRef, 
    private updateService: UpdateService) {

    this._reports = new ObservableArray<Report>();
    this.subscription = updateService.reportData$.subscribe(
        (res) => {
            console.log("reports listing in reports component = "+JSON.stringify(res));

            let data=JSON.parse(JSON.stringify(res));

            if (data["reports"]=="No Reports") {                 
                // No reports to show
            } else {  
                var status_text;
                var status_class;
                for (let i = 0; i < data.reportid.length; i++) {
                    var status_codes=this.displayReportStatus(data.report_status[i]);
                    status_text=status_codes[0];
                    status_class=status_codes[1];

                    this._reports.push(new Report(data.reportid[i], data.report_name[i], data.report_status[i], data.report_value[i], status_text, status_class, data.report_justification));
                }
                this._changeDetectionRef.markForCheck();
                if (!this._changeDetectionRef['destroyed']) {
                    this._changeDetectionRef.detectChanges();
                }

            }

        }
    );
}
public get reports(): ObservableArray<Report> {
    return this._reports;
} 

The line

console.log("reports listing in reports component = "+JSON.stringify(data));

is outputting the reports data no problem so the service is returning the correct data.

However the template is not displaying the formatted list of reports. It is blank. The template looks like:

   <!--
    <RadListView [items]="reports" (itemTap)="onReportItemTap($event)" >
    //-->
    <RadListView [items]="reports" >
        <ng-template tkListItemTemplate let-item="item">
            <StackLayout class="itemTemplateStackLayout" orientation="vertical">

                    <StackLayout class="reportStackLayout" orientation="vertical">

                        <Label class="labelName blue_text bold_text list-group-item" [nsRouterLink]="['../report', item.reportid]" [text]="item.report_name"></Label>


                        <GridLayout class="reportDetailsGridLayout" columns="*, *">
                            <Label row="0" col="0" horizontalAlignment="left" [class]="item.status_class" class="labelStatus"  [text]="item.status_text" textWrap="true"></Label>
                            <Label row="0" col="1" horizontalAlignment="right" class="labelValue green_text bold_text" [text]="item.report_value" textWrap="true"></Label>
                        </GridLayout>

                    </StackLayout>

            </StackLayout>
        </ng-template>         
    </RadListView>
</GridLayout>

Any ideas what I am doing wrong.

Hope I have explained sufficiently - please let me know if I need to clarify anything further.

Thanks.

EDIT: October 9th.

Here is the reports.component.ts as it is now. Still not updating the view.

import { Component, ChangeDetectorRef, OnInit } from "@angular/core";

import { ReportComponent } from "./report.component";
import { Report } from "../shared/report/report.model";
import { Expense } from "../shared/expense/expense.model";
import { ReportService } from "../shared/report/report.service";
import { ExpenseService } from "../shared/expense/expense.service";
import { UpdateService } from "../shared/update.service";
import { Subject, Subscription } from 'rxjs';
import { ActivatedRoute, Router } from "@angular/router";
import { NativeScriptRouterModule } from "nativescript-angular/router"; 
import { Page } from "tns-core-modules/ui/page";
import { ObservableArray } from "tns-core-modules/data/observable-array";
import { ListViewEventData } from "nativescript-ui-listview";
import { RadListView } from "nativescript-ui-listview";


import { RouterExtensions } from "nativescript-angular/router";
import * as ApplicationSettings from "application-settings";
import {getBoolean, setBoolean, getNumber, setNumber, getString, setString, hasKey, remove, clear} from "tns-core-modules/application-settings";
import { Injectable } from "@angular/core";

declare var module: {
    id: string;
 }
@Component({
selector: "Reports",
moduleId: module.id,
providers: [ReportService, ExpenseService, UpdateService],
templateUrl: "./reports.component.html",
styleUrls: ["./reports.component.css"]
})


export class ReportsComponent implements OnInit {

//private report: Report;
private _reports: ObservableArray<Report>;
private _tempreports: ObservableArray<Report>;
private _expenses: ObservableArray<Expense>;
header: string;
report_status: Array<String>;
isLoading = true;
foo: string;

private listView: RadListView;

subscription: Subscription;

constructor(private router: Router, 
    private route: ActivatedRoute,
    private reportService: ReportService, 
    private expenseService: ExpenseService,
    private _changeDetectionRef: ChangeDetectorRef, 
    private updateService: UpdateService) {

        this.subscription = this.updateService.reportData$.subscribe(
            (res) => {
                console.log("isLoading="+this.isLoading);
                console.log("reports listing in reports component = "+JSON.stringify(res));


                this._reports = new ObservableArray<Report>();
                this._tempreports = new ObservableArray<Report>();

                let data=JSON.parse(JSON.stringify(res));

                if (data["reports"]=="No Reports") {                 
                    // No reports to show
                } else {  
                    var status_text;
                    var status_class;
                    for (let i = 0; i < data.reportid.length; i++) {
                        var status_codes=this.displayReportStatus(data.report_status[i]);
                        status_text=status_codes[0];
                        status_class=status_codes[1];

                        this._tempreports.push(new Report(data.reportid[i], data.report_name[i], data.report_status[i], data.report_value[i], status_text, status_class, data.report_justification));
                    }
                    this._reports = this._tempreports;
                    this._changeDetectionRef.markForCheck();
                    if (!this._changeDetectionRef['destroyed']) {
                        this._changeDetectionRef.detectChanges();
                    }

                    this.isLoading=false;
                    //this.listView.refresh();                      
                    console.log("isLoading="+this.isLoading);   

                }

            }
        );

}
onListLoaded(args) {
    console.log("In onListLoaded");
    this.listView = args.object;
    this.listView.refresh();     
}

public get reports(): ObservableArray<Report> {
    //console.log("Where are the focking reports");
    return this._reports;
} 

解决方案

Which platform(ios/android) are you testing this? It is very important for ios to provide height and width to the listview or it's parent component. otherwise You code looks fine to me at very first glance. There are couple of other thing you could to try for further debugging

  1. Subscribe in (loaded) mthod of RadListView.

  2. Try to assign listview in loaded like this

onListLoaded(args) {this.listView = args.object;}

and refresh the listview by this.listview.refresh() once you have the reports data. 3. Have an activityIndicator first and hide the list. Hide the indicator once you have reports and make lost visible.

<ActivityIndicator [busy]="isLoading" [visibility]="isLoading ? 'visible' : 'collapse'" row="2" horizontalAlignment="center"></ActivityIndicator>

4. Push data to temp array and once all items are pused, assign that temp array to reports.

_tempreports.push(new Report(data.reportid[i], data.report_name[i], data.report_status[i], data.report_value[i], status_text, status_class, data.report_justification));
this._reports = _tempreports;

这篇关于在2个组件之间共享来自服务器的JSON数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆