2016-04-17 59 views
5

我有一个简单的组件,它只是呈现一个进度条。当变量发生变化时,Angular2组件视图不会更新

它初始化很好,进度传递给它很好,但模板没有用新值更新。

import {Component} from 'angular2/core'; 

@Component({ 
    selector : 'progress-bar', 
    template : ` 
    <div class="progress-container"> 
     <div>{{currentProgress}}</div> 
     <div [style.width.%]="currentProgress" class="progress"></div> 
    </div> 
    `, 
    styles: [ 
    '.progress-container {width: 100%; height: 5px}', 
    '.progress {background-color: #8BC34A; height:5px}' 
    ] 
}) 

export class ProgressBar { 
    currentProgress: number; 

    constructor() { 
    this.currentProgress = 0; 
    } 

    onProgress(progress: number) { 
    console.log(progress) //consoles correct percentages 
    this.currentProgress = progress; 
    } 

    reset() { 
    console.log(this.currentProgress) //is 100 
    this.currentProgress = 0; 
    } 
} 
~ 

别处

ngOnInit() { 
    this.httpFileService.progress$.subscribe((progress: number) => this.onProgress(progress)); 
    } 

    onProgress(progress: number) { 
    this.progressBar.onProgress(progress*100); 
    } 

我觉得我失去了一些东西非常的补救。

+0

如果您将更新您的问题以向我展示'onProgress'是如何被调用的,我可能会让我的答案对您更有帮助 - 我怀疑这里有更深的反模式。 – drewmoore

+0

添加了onProgress部件。它通过我订阅的xhr onprogress检索。 – Dreamlines

+0

我是对的:-)只需一秒钟,我就会更新 – drewmoore

回答

11

你正在以一种与框架相互作用的方式来解决这个问题,并且会导致大量的哭闹和咬牙切齿。

现在,您正在手动订阅observable - httpFileService.progress$ - 然后手动更新子组件ProgressBar上的属性,绕过角度的更改检测机制 - 这就是UI未更新的原因。你可能设置此属性后,手动火灾变化检测和UI会更新如预期 - 但再次,你会对框架工作,所以让我们看看如何使用它,而不是:

我假设“别处”是您的ProgressBar组件的父级 - 我们称之为ElsewhereComponent

@Component({ 
    selector: 'elsewhere', 
    directives: [ProgressBar], 
    template: ` 
    <div> 
     <progress-bar [currentProgress]="httpFileService.progress$"></progress-bar> 
    </div> 
    ` 
}) 
class ElsewhereComponent { 
    // you can remove the ngOnInit and onProgress functions you posted 
    // you also don't need a reference to the child ProgressBar component 
    // ... whatever else you have in this class ... 
} 

这里要注意的最重要的事情是progress-bar部件上添加[currentProgress]:这是告诉角度,有一个名为currentProgress应该被绑定到httpFileService.progress$该组件的输入特性。

但是你现在已经对角度说谎了 - 因为它站立起来,ProgressBar根本没有任何输入,当它试图将这个不存在的属性绑定到给定值时,angular会告诉你它。因此,我们需要添加输入属性,这样做的最佳方式是与Input()装饰:

@Component({ 
    selector : 'progress-bar', 
    pipes: [AsyncPipe] //import this from angular2/core 
    template : ` 
    <div class="progress-container"> 
     <div>{{currentProgress | async}}</div> 
     <div [style.width.%]="currentProgress | async" class="progress"></div> 
    </div> 
    ` 
}) 
export class ProgressBar { 
    @Input() currentProgress: Observable<number>; 
    ... 
    constructor(){ 
    // remove the line you have in here now 
    } 

} 

这里有两个关键需要注意的差异:首先,@Input()告诉角度说currentProgress是输入属性。我们还改变了从number该属性的类型Observable<number> - 这不是绝对必要的,但因为它允许第二个关键的区别是非常有用:

AsyncPipe已添加到组件的pipes,在上述两种使用其模板绑定到currentProgress。这很有用,因为它告诉angular处理所有订阅Observable的脏东西,并在每次发布新值时更新UI。

而这一切都需要:酒吧的两个宽度和它上面现在会自动更新,以反映从httpFileService发出的价值观,你没得的 势在必行一行代码写入文本实现它。

+0

我执行上述操作,但我面临的问题是进度条不会自动更新。但是,如果我点击栏,它运作良好。该栏会显示来自观察对象的当前值。任何想法? – Hammer

+0

@Hammer你描述的是变更检测问题 – drewmoore

+0

是的。同意,但我比较代码与你在这里共享没有任何线索..我粘贴我的代码在这里,感谢如果你可以帮助看看?韩国社交协会。 http://stackoverflow.com/questions/37046757/ui-is-not-updated-automatically-when-value-is-available-from-the-observable – Hammer

相关问题