2017-07-24 32 views
0

1)我有SiteMap組件顯示: a)3按鈕:確認,再次上傳文件,更新UI(用於測試) b)組件TreeView:這需要一個數組作爲輸入並在UI上顯示它 。無法更新UI,即使模型更改的數據(使用Angular 4 - 可觀察數據)

<!--siteMap-component.html --> 
<div class="tree"> 
    <tree-view [siteTree]="siteMapTree"> 

    </tree-view> 
</div> 
<div class="col-xs-12"> 
    <button type="button" class="pull-right btn-primary" (click)="approveAndUploadLandingPages()">Confirm</button> 
    <button type="button" class="pull-left btn-inverse" (click)="updateSiteMapTree()">Refresh UI</button> 
    <button type="button" class="pull-left btn-inverse" (click)="uploadAgain()">Upload Again</button> 
</div> 

2)我有一個siteMapDataObservable,它是用一個值初始化的。現在,只要有來自updateSiteMapTree()的this.siteMapDataObservable.next()調用,就會更新此Observable的值。

// SitemapComponent 
import ... 
@Component({ 
    selector: 'app-gb-sitemap', 
    templateUrl: './sitemap.component.html', 
    styleUrls: ['./sitemap.component.scss'], 
    encapsulation: ViewEncapsulation.None 
}) 
export class SitemapComponent implements OnInit { 

    siteMapTree: Array<any>; 
    siteMapDataObservable: BehaviorSubject<Object> = new BehaviorSubject<Object>(this.contactServerService.getSiteMapObject()); 


    constructor(private contactServerService: ContactServerService, private route: ActivatedRoute, private router: Router, public modal: Modal) { 
    } 

    updateSiteMapTree() { 
    this.siteMapDataObservable.next(this.contactServerService.getSiteMapObject());// this.contactServerService.getSiteMapObject() retrieves the data from sessionStorage 
    } 

    uploadAgain() { 
    return this.modal.open(CustomModalComponent, overlayConfigFactory({ }, BSModalContext)); 
    } 

    rejectUpload() { 
    this.router.navigate(['/home']); 
    this.clearSessionStorage(); 
    } 

    approveAndUploadLandingPages() { 
    this.contactServerService.uploadLandingPages(this.landingPagesObj) 
     .subscribe(
     (response) => { 
      console.log(response); 
      this.clearSessionStorage(); 
      this.router.navigate(['/']); 
     }, 
     (error) => console.log(error) 
    ); 
    } 

    clearSessionStorage() { 
    sessionStorage.removeItem('siteMapTree'); 
    } 


    ngOnInit() { 
    this.siteMapDataObservable 
     .subscribe(
     siteMapTreeObj => { 
      this.siteMapTree = [siteMapTreeObj['tree']]; 
     } 
    ); 
    } 
} 

3)Upload Again Button打開模式; CustomModalComponent用於接收用戶的另一個文件,並在http的回調中修改數據模型,並調用SiteMapComponent中的updateSiteMapTree()以獲取siteMapTree的更新。

// CustomModalComponent 
import ... 
@Component({ 
    selector: 'modal-content', 
    templateUrl: './custom-modal-sample.html', 
    encapsulation: ViewEncapsulation.None, 
    providers: [SitemapComponent], 
    styleUrls: ['./custom-modal-sample.scss'] 
}) 


export class CustomModalComponent implements OnInit { 
    fileTypes: Array<string>; 

    private uploadExcelUrl: string; 
    public uploaderExcel: FileUploader; 

    constructor(private router: Router, public dialog: DialogRef<any>, private contactServerService: ContactServerService, 
       private siteMapComponent: SitemapComponent) { 
    this.fileTypes = ['.xls', '.xlsx']; 

    this.uploadExcelUrl = this.contactServerService.getExcelUploadUrl(); 
    this.uploaderExcel = new FileUploader({url: this.uploadExcelUrl}); 
    } 

    ngOnInit() { 

    this.uploaderExcel.onSuccessItem = function(fileItem, response, status, headers) { 
     fileItem.remove(); 

     const RESPONSE_DATA = JSON.parse(response); 
     sessionStorage.setItem('landingPagesTree', JSON.stringify(RESPONSE_DATA)); 

     dialogBox.dismiss(); 

    }; 

    this.siteMapComponent.updateSiteMapTree(); 
    } 

    getNextRouteState() { 
    return this.router; 
    } 

    clearError() { 
    this.dialog.dismiss(); 
    } 
} 

發現:1)從CustomModalComponent到updateSiteMapTree()的調用中SiteMapComponent更新「siteMapTree」,但更改不會反映在用戶界面中。

2)爲了測試,我在SiteMapComponent組件中有一個按鈕Refresh UI,它也調用updateSiteMapTree()。但是,單擊此按鈕將更新UI。

問題: 1)爲什麼當我調用SiteMapComponent updateSiteMapTree()從CustomModalComponent甚至當我的數據模型改變沒有更新我的UI。

2)當我通過單擊相同組件中的按鈕來調用SiteMapComponent中的updateSiteMapTree()時,UI是如何改變的。

編輯: 添加TreeViewComponent

import ...; 

@Component({ 
    selector: 'tree-view', 
    templateUrl: './tree-view.component.html', 
    styleUrls: ['./tree-view.component.css'], 
    changeDetection: ChangeDetectionStrategy.OnPush 
}) 

export class TreeViewComponent implements OnInit, OnChanges { 

    @Input() siteTree: Array<any>; 

    warnings: Array<string>; 

    constructor() { 
    this.warnings = []; 
    } 

    ngOnInit() { 
    } 

    ngOnChanges (...args: any[]) { 
    console.log('OnChange'); 
    console.log(this.siteTree); 
    } 

    toggle(subtree) { 
    subtree.showChild = !subtree.showChild; 
    } 
} 

回答

1

您可以使用tick()方法從ApplicationRef強制檢測的變化。

@Injectable() 
export class Service { 

    constructor(private appref: ApplicationRef){} 

    public someMethod():void { 
      //some actions, ie pushing next value to observable 
      this.appref.tick(); 
    } 
} 

https://angular.io/api/core/ApplicationRef

+0

在SitemapComponent的 'updateSiteMapTree()',I加入this.appref.tick();最後。我在最後添加它,以便一旦我的next()函數調用this.siteMapDataObservable.subscribe(),只有appref.tick()被調用。但是UI仍然沒有得到更新。 –

+0

您是否更改了檢測策略? –

+0

如何更改檢測策略? –