2017-02-09 163 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

相關問題