2017-02-09 162 views
0

目标:我想创建一个具有可订阅数组(BehaviorSubject)的服务,这样当我更新服务中的数据时,这些更改将反映在客户端正在使用它的组件。我决定首先尝试在附加或更改项目时保留服务器中的持久性列表,然后再担心保持数据与服务器的一致性。每个组件不共享一个服务的实例

问题:

workCategories:Rx.BehaviorSubject>在服务似乎没有保持它就是它的分配数据。从第一个客户端组件调用它时,然后当第二个客户端组件使用该服务时,workCategories再次为空。

服务

import { Component, Injectable } from "@angular/core"; 
import { Http, Response, Headers, RequestOptions, RequestMethod, Request } from "@angular/http"; 
import { WorkCategory } from "./models"; 
import { Observable } from "rxjs/Observable"; 
import * as Rx from "rxjs/Rx"; 


@Injectable() 
export class WorkCategoryService { 

    public workCategories: Rx.BehaviorSubject<Array<WorkCategory>>; 

    private _workCategories: Array<WorkCategory> = []; 

    constructor(public http: Http) { 
     console.log("!!!!WorkCat Service Constructor Called!!!"); 
     this.getWorkCategories(); 
    } 

    addWorkCategory(wc: WorkCategory): number { 
     //** when this is called after component is instantiated and getWorkCategories() is called this.workCategories is null 
     console.log("Add Work Category Called in Service for \"" + wc.name + "\""); 

     let newID: number; 
     let headers = new Headers(); 
     headers.append('Content-Type', 'application/json'); 
     let options = new RequestOptions({ headers: headers }); 
     let blah = this.http.post('./api/workcategories', JSON.stringify(wc), options).subscribe((res: Response) => newID = res.json()); 
     if (this._workCategories != null) { 
      console.log("Added to private"); 
      this._workCategories.push(wc); 
     } 

     //** fails here and the page is reloaded due to this.workCategories being null 
     this.workCategories.next(this._workCategories); 

     return newID; 
    } 

    getWorkCategories(): Observable<Array<WorkCategory>> { 
     console.log("Get Work Category Called in Service"); 

     var blah = this.http.get('./api/workcategories') 
      .map(this.WorkCategoriesResponseMapper) 
     console.log("Get Work Category Done in Service"); 
     return blah; 

    } 

    WorkCategoriesResponseMapper(response: Response) { 
     var temp = response.json(); 

     if (this.workCategories == null) {    
      this._workCategories = temp;   
      this.workCategories = new Rx.BehaviorSubject(this._workCategories); 
     } 
     else { 
      this._workCategories = temp; 
      this.workCategories.next(this._workCategories); 
     } 
     return temp; 
    } 
} 

1客户端组件

这就要求this.workCatServ.getWorkCategories()和订阅它。

import { Component, Input, Injectable, ViewChild, EventEmitter, Output, } from "@angular/core"; 
import { Http, Response, Headers, RequestOptions, RequestMethod, Request } from "@angular/http"; 
import { WorkCategory } from "./models"; 
import { WorkCategoryService } from "./workcategories.service"; 
//import { Observable } from 'rxjs/Observable'; 
import * as Rx from "rxjs/Rx"; 
import { TreeNode, MenuItem, Message } from 'primeng/primeng'; 
import { CategoryAdderUpdateComponent } from "./category-adder-update.component"; 


@Component({ 
    selector: 'workcategories_view', 
    //providers: [WorkCategoryService], 
    templateUrl: './app/workcategories-view.html' 
}) 

@Injectable() 
export class WorkCategoriesViewComponent { 
    @ViewChild(CategoryAdderUpdateComponent) private CategoryCU: CategoryAdderUpdateComponent; 
    @Output() GrowlMsg = new EventEmitter<Message>(); 
    workCats: Array<WorkCategory>; 
    tree: TreeNode[]; 
    selectedNode: TreeNode; 
    selectedCategory: WorkCategory = new WorkCategory(-1,"Blank",-2); 
    contextMenuItems: MenuItem[]; 
    CUWorkCatVisible: boolean = false; 
    CUWorkCatEdit: boolean = false; 
    CUViewHeader: string; 

    constructor(public http: Http, private workCatServ: WorkCategoryService) { 
    } 

    ngOnInit() { 
     console.log("Work Categories view called"); 
     this.workCatServ.getWorkCategories().subscribe(result => this.convertToTreeNodes(result), error => console.error(error),() => { }); 

     this.contextMenuItems = [ 
      { 
       label: 'Add', 
       icon: 'fa-plus', 
       command: (event) => { this.displayAddWorkCat() } 
      }, 
      { 
       label: 'Edit', 
       icon: 'fa-edit', 
       command: (event) => { this.displayEditWorkCat() }   
      }, 
      { 
       label: 'Delete', 
       icon: 'fa-eraser', 
       command: (event) => { this.displayDeleteWorkCat() } 

      } 
     ]; 

    } 


    displayAddWorkCat() { 

     this.selectedCategory = this.workCats.find(b => b.id == this.selectedNode.data); 
     //console.log("Add " + this.selectedCategory.name); 
     this.CategoryCU.AddView(this.selectedCategory); 
     this.CUViewHeader = "Add Work Category"; 
     /*this.workCatServ.findWorkCategorey(this.selectedNode.data).map(result => { 
      console.log("Done"); 
      this.selectedCategory = result; 

     }); 
     */ 

     this.CUWorkCatVisible = true; 

    } 

    displayEditWorkCat() {     
     this.selectedCategory = this.workCats.find(x => x.id == this.selectedNode.data); 
     //console.log("Edit " + this.selectedCategory.name); 
     this.CategoryCU.UpdateView(this.selectedCategory); 
     this.CUViewHeader = "Edit \"" + this.selectedCategory.name + "\" Work Category"; 

     /*this.workCatServ.findWorkCategory(this.selectedNode.data).map(result => { 
      console.log("Done"); 
      this.selectedCategory = result; 

     });*/ 

     this.CUWorkCatVisible = true; 

    } 

    displayDeleteWorkCat() { 
     console.log("Delete"); 

    } 

    passUpGrowlMsg(msg: Message) { 
     this.GrowlMsg.emit(msg); 
    } 

    MyTreeWalker(nodeId: number = 0, parentNode: TreeNode = null): boolean { 
     let blah = this.workCats.filter(x => x.parentId == nodeId); 
     if (blah.length == 0) { 
      //console.log("Node " + nodeId + " is leaf"); 
      return false; 
     } 

     //console.log("Node " + nodeId + " is branch, " + blah.length + " children"); 


     if (nodeId != 0) { 

      for (var b of blah) { 
       var TempNode: TreeNode = { label: b.name, data: b.id, parent: parentNode, children: [] }; 

       this.MyTreeWalker(b.id, TempNode); 
       //console.log("Control Passed Back"); 
       parentNode.children.push(TempNode); 
       //console.log("Pass End"); 
      } 
     } else { 
      for (var c of blah) { 
       var TempNode: TreeNode = { label: c.name, data: c.id, parent: parentNode, children: [] }; 
       this.MyTreeWalker(c.id, TempNode); 
       //console.log("R - Control Passed Back"); 
       this.tree.push(TempNode); 
       //console.log("R - Pass End"); 
      }      
     } 
     //console.log("Node: " + nodeId + " Exit"); 
     return true; 
    } 

    convertToTreeNodes(cats: WorkCategory[]) { 
     console.log("Tree Updated Called"); 
     this.tree = new Array<TreeNode>(); 
     this.workCats = cats; 

     this.MyTreeWalker(); 
    } 
} 

第二客户端组件

这在服务调用addWorkCategory()

import { Component, EventEmitter, Output, Input } from "@angular/core"; 
import { Http, Response } from "@angular/http"; 
import { WorkCategory} from "./models"; 
import { WorkCategoryService } from "./workcategories.service"; 
import { Message } from 'primeng/primeng'; 
import 'rxjs/add/operator/map'; 

@Component({ 
    selector: 'category-adder-update', 
    //providers: [WorkCategoryService], 
    templateUrl: './app/category-adder-update.html' 

}) 

export class CategoryAdderUpdateComponent { 

    @Output() GrowlMsg = new EventEmitter<Message>(); 
    edit: boolean; 
    workcategories: Array<WorkCategory> = []; 
    tempCategory: WorkCategory; 
    parentCategory: WorkCategory; 
    buttonText: string = "Blanky Blank"; 



    constructor(public http: Http, public workCategoriesServ: WorkCategoryService) { 
     this.tempCategory = new WorkCategory(null,"",null); 
     console.log("Category Adder-Update Called"); 
    } 

    AddView(parentCat: WorkCategory) { 
     this.edit = false; 
     this.parentCategory = parentCat 
     this.tempCategory = new WorkCategory(null, "", parentCat.id); 
     this.buttonText = "Add Work Category"; 

    } 

    UpdateView(cat: WorkCategory) { 
     this.edit = true; 
     this.parentCategory = null; 
     this.tempCategory = cat; 
     this.buttonText = "Update Work Category"; 
    } 

    blahSubmit() { 
     if (this.edit) { 
      this.updateWorkCategory(); 
     } else { 
      this.addWorkCategory(); 
     } 
    } 


    getWorkCategories() { 
     console.log("jobs get called"); 
     this.workCategoriesServ.getWorkCategories().subscribe(
      result => this.workcategories = result, 
      error => console.error, 
      () => console.log('workcategories loaded: ' + this.workcategories.length)); 
    } 

    addWorkCategory(): void {  
     this.GrowlMsg.emit({ severity: 'info', summary: 'Category Added', detail: "Category " + this.tempCategory.name + " added to " + this.parentCategory.name });  
     if (this.workCategoriesServ.addWorkCategory(this.tempCategory) != null) { 
      console.log("New Work Category Submitted"); 
     } 
     else { 
      console.error("New Work Category NOT Submitted"); 
     } 

    } 


} 

APP模块

@NgModule({ 
    imports: [BrowserModule, HttpModule, FormsModule, DataTableModule, CalendarModule, TreeModule, TabViewModule, GrowlModule, DialogModule, ContextMenuModule, RouterModule.forRoot(appRoutes) ], 
    declarations: [AppComponent, TicketAdderComponent, JobsViewComponent, TimeEntriesViewComponent, WorkCategoriesViewComponent, CategoryAdderUpdateComponent], 
    providers: [WorkCategoryService], 
    entryComponents: [TicketAdderComponent], 
    bootstrap: [AppComponent ] 
}) 
export class AppModule { } 
+0

它不是非常持久,因为它接缝。 –

+0

@RomanC Whjat是否意味着? – TheColonel26

+1

在计算机科学中,持久性指的是超越创造它的过程的状态特征。这在实践中通过将状态作为数据存储在计算机数据存储器中来实现。程序必须向存储设备传输数据和从存储设备传输数据,并且必须提供从本地编程语言数据结构到存储设备数据结构的映射。 –

回答

2

您提供在每个补偿服务onent。你想要做的是在AppModule中提供服务,然后这两个组件将共享相同的服务。

+0

我已经将WorkCategoryService注释为两个组件中的提供者,并将其添加到AppModule中,但我仍然得到相同的结果。 – TheColonel26

+1

@TheColonel26这是不太可能的,它会是相同的结果,因为这是A2 DI的工作原理。答案是正确的,我建议仔细检查一下,你是否已将这些更改应用到您在浏览器中运行的代码。否则,该问题需要[MCVE](http://stackoverflow.com/help/mcve),可以复制该问题。 – estus

相关问题