2016-03-28 24 views
15

我有一個自定義選擇組件,它在您點擊li項目時設置模型,但由於我每次更改模型時都手動調用this.modelChange.next(this.model),所以我很想避免這種混亂和可重複的操作。如何在每次模型角度2變化時調用函數?

所以我的問題是,如果有類似$scope.$watch的東西,我可以觀察一個值是否發生變化,然後每次發生時調用this.modelChange.next(this.model)

我一直在閱讀關於Observables,但我無法弄清楚這應該如何用於一個簡單的值,因爲我看到的所有示例都與外部api:s的異步請求。

當然,必須有一個更簡單的方法來實現這一目標?

(不是說我不能使用ngModelChanges,因爲我實際上沒有使用輸入)。

import {Component, Input, Output, EventEmitter, OnInit, OnChanges} from 'angular2/core'; 

@Component({ 
    selector: 'form-select', 
    templateUrl: './app/assets/scripts/modules/form-controls/form-select/form-select.component.html', 
    styleUrls: ['./app/assets/scripts/modules/form-controls/form-select/form-select.component.css'], 
    inputs: [ 
    'options', 
    'callback', 
    'model', 
    'label' 
    ] 
}) 

export class FormSelectComponent implements OnInit, OnChanges { 
    @Input() model: any; 
    @Output() modelChange: EventEmitter = new EventEmitter(); 

    public isOpen: boolean = false; 

    ngOnInit() { 

    if (!this.model) { 
     this.model = {}; 
    } 

    for (var option of this.options) { 

     if (option.model == (this.model.model || this.model)) { 
     this.model = option; 

     } 
    } 
    } 

    ngOnChanges(changes: {[model: any]: SimpleChange}) { 
    console.log(changes); 
    this.modelChange.next(changes['model'].currentValue); 
    } 

    toggle() { 
    this.isOpen = !this.isOpen; 
    } 

    close() { 
    this.isOpen = false; 
    } 

    select(option, callback) { 
    this.model = option; 
    this.close(); 

    callback ? callback() : false; 
    } 

    isSelected(option) { 
    return option.model === this.model.model; 
    } 
} 

編輯:我嘗試使用ngOnChanges(見上更新的代碼),但它只能在初始化運行一次,然後在沒有檢測的變化。有什麼不對?

回答

18

所以我的問題是,如果有類似$範圍的東西$看我在哪裏可以看,如果輸入屬性model的值更改。

如果model是一個JavaScript基本類型(數字,字符串,布爾值),那麼你就可以實現ngOnChanges()要通知符變化。請參閱cookbook examplelifecycle doc, OnChanges section
另一種選擇是使用setter和getter。見cookbook example

如果model是一個JavaScript引用類型(數組,對象,日期等),那麼你是怎樣判斷的變化取決於如何模型的變化:

  • 如果參考模型的變化(即,您指定一個新的數組,或一個新的對象等),您可以實現ngOnChanges()以通知更改,就像原始類型一樣。然而,如果模型引用沒有改變,但模型的某些屬性發生了變化(例如,數組項的值發生了變化,或者數組項被添加或刪除,或者對象屬性值發生變化),但是,如果模型引用不發生變化,您可以執行ngDoCheck()來實現您自己的更改檢測邏輯。
    lifecycle doc, DoCheck section
+0

Set/get不起作用它只是拋出一大堆錯誤,ngOnChanges不起作用,因爲我改變了組件內部的值,然後用兩種方式將它綁定到父組件。 ngDoCheck()似乎是過度殺傷,因爲我只需要知道它是否發生了變化,我不需要任何特定的邏輯。我真正喜歡的是使用觀察者,但我正在爲如何實施而失去理智。你能告訴我如何與觀察員達成這個目標嗎?使用我的代碼,不是一些與我的用例完全不同的隨機示例。我會很感激它像瘋了一樣。 – Chrillewoodz

+0

關於ngDoCheck(),Angular不能神奇地知道我們的ReferenceTypes的結構,所以如果我們必須爲他們編寫我們自己的變化檢測邏輯,這並不過分。 (這在我引用的生命週期文檔中討論過。)由於'model'是一個輸入屬性,我將使用ngDoCheck()而不是observable。你有一個簡單的蹦牀,只是演示非工作片? –

+0

「由於model是一個輸入屬性,所以我會使用ngDoCheck()而不是observable。」爲什麼是這樣?你應該爲http請求以外的其他應用程序使用observables嗎?通過檢查以前的模型,我得到它與doCheck一起工作,或者它最終成爲一個無限循環。 – Chrillewoodz

0

您可以做一個model的getter/setter方法或通過添加ngOnChanges(changes) {}方法被稱爲每一個@Input()值更改後的時間實現OnChanges

從文檔的ngOnChanges()例如(上面鏈接):

@Component({ 
    selector: 'my-cmp', 
    template: `<p>myProp = {{myProp}}</p>` 
}) 
class MyComponent implements OnChanges { 
    @Input() myProp: any; 
    ngOnChanges(changes: {[propName: string]: SimpleChange}) { 
    console.log('ngOnChanges - myProp = ' + changes['myProp'].currentValue); 
    } 
} 
@Component({ 
    selector: 'app', 
    template: ` 
    <button (click)="value = value + 1">Change MyComponent</button> 
    <my-cmp [my-prop]="value"></my-cmp>`, 
    directives: [MyComponent] 
}) 
export class App { 
    value = 0; 
} 
bootstrap(App).catch(err => console.error(err)); 

更新

如果的model變化的內部狀態,但不是model本身(不同model實例)然後改變檢測不承認它。您需要實現自己的機制來通知感興趣的代碼,例如在model中使用Observable,它發出組件可以訂閱的更改事件。

此外,當model通過數據綁定(當someFieldInParent<my-comp [model]="someFieldInParent">已經改變和角傳入MyComponent新值model

return option.model === this.model.model;改變ngOnChanges()僅稱爲不引起ngOnChanges()被調用。對於這工作的getter/setter方法是一種更適合

+0

好吧,我會看ngOnChanges,但請包括一些示例代碼,如果你還想要你的答案以獲得接受;) – Chrillewoodz

+0

完成。 。 。 。 。 。 –

+0

檢查更新後的問題,看起來似乎無法在首次執行後檢測到任何問題。 – Chrillewoodz

2

如果選擇自定義組件在內部使用的表單輸入(S),我會充分利用它/他們ngModelChange事件:

<select [ngModel]="..." (ngModelUpdate)="triggerUpdate($event)">…</select> 

或valueChanges可觀察到的相應控件(如果有的話)。在模板:

<select [ngFormControl]="myForm.controls.selectCtrl">…</select> 

在組件:

myForm.controls.selectCtrl.valueChanges.subscribe(newValue => { 
    (...) 
}); 
+0

這個是我爲什麼要去實際的表單元素,但它不適用於我使用ul/li元素的自定義選擇,所以我認爲一個可觀察的解決方案就是要走的路。我可以理解他們是如何工作的,哈哈。 – Chrillewoodz

+0

只是想一想:爲什麼不用你選擇的組件之一調用emit方法? ;-) –

+0

因爲它不是模型改變的唯一地方,它可以改變3種不同的方式。這就是我最初的做法,但後來認識到,模型在首次接收現有值時也必須更新,並且如果沒有值並且模型必須設置爲空對象。 – Chrillewoodz

相關問題