2017-01-19 57 views
4

我遇到了一個問題,在那裏試圖更新knockoutJS可觀察到的動態可觀察不會更新UI。Knockout計算Observable不更新UI

我在複選框上實現了父 - 子依賴關係以下規則管理交互。

  1. 當父複選框被選中時,所有的子複選框都被選中。
  2. 當父複選框未選中時,則所有子複選框均未選中。
  3. 當任何一個子複選框未選中時,則應該取消選中父複選框。
  4. 當所有的孩子複選框被選中時,然後應檢查父複選框。

現在我有一個場景,父 - 子依賴關係行爲是動態的,即上述規則僅在用戶單擊按鈕時纔開始工作。

我有一個實現,其中父複選框綁定到一個可觀察的屬性,後來該屬性被覆蓋到一個新的計算Observable。 在更改爲計算的可觀察值之後,前2條規則(規則1 & 2)有效,但最後2條規則(規則3 & 4)停止工作。我可以在調試器中看到返回值正確返回,但不會更新UI。

爲了證明我的問題,我已創建2 JS小提琴

  1. 小提琴在https://jsfiddle.net/agalo/rjc1Lsbe/4/描述的是父子關係的規則工作正常的情況。在這種情況下,計算的Observable屬性最初在對象上定義,並且不會動態更改。這工作完美。
  2. 小提琴https://jsfiddle.net/agalo/uc7yt9tw/4/描述了我目前的規則3和規則4不起作用的實現。在這種情況下,通過單擊按鈕,Observable屬性將被計算的Observable覆蓋。因此,最初父母子女關係不是強制執行的,但是通過點擊按鈕,強制執行關係。

我不想尋找替代解決方案,但我有興趣瞭解爲什麼第二個小提琴顯示的行爲。

function ViewModel(){ 
 
    var self = this; 
 
    
 
    var childrenArray = [ {isSelected : ko.observable(true)}, 
 
    \t \t \t \t \t \t {isSelected : ko.observable(true)}, 
 
          {isSelected : ko.observable(true)}, 
 
          {isSelected : ko.observable(true)}]; 
 
    self.parentChildData = { 
 
          parentCheckBox: ko.observable(false), 
 
          children: ko.observableArray([]) 
 
          }; 
 
    self.parentChildData.children(childrenArray); 
 
    
 
    self.makeDependent = function(){ 
 
\t \t self.parentChildData.parentCheckBox = ko.computed({ 
 

 
        read: function() { 
 
         var anyChildUnChecked = ko.utils.arrayFirst(self.parentChildData.children(), function (childCheckBox) { 
 
           return !childCheckBox.isSelected(); 
 
          }); 
 
          var result = anyChildUnChecked == null; 
 
\t \t \t \t \t \t \t return result; 
 
         
 
         //return false; 
 
        }, 
 

 
        write: function (value) { 
 
           ko.utils.arrayForEach(self.parentChildData.children(), function (childCheckBox) { 
 
           childCheckBox.isSelected(value); 
 
          }); 
 
        } 
 
     })}; 
 
\t 
 
    return self; \t 
 
\t 
 
} 
 

 
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script> 
 
<p> 
 
Describes my current implementation for which Rule 3 and 4 are not working. In this case, the Observable property is overridden with the computed Observable on the click of the button. So, initially the parent child relationship is not enforced, but on click of button the relationship is enforced. 
 
</p> 
 

 
<p> 
 
After clicking the button, the first 2 Rules (Rule 1 and 2) works but last 2 Rule (Rule 3 and 4) stops working. I can see in the debugger that the return value is correctly returned but it doesn't Update the UI. 
 

 
</p> 
 
<div id="parent"> 
 
parent <input type="checkbox" data-bind="checked:parentChildData.parentCheckBox"/> 
 
    
 
    <br/> 
 
    <div id="child"> 
 
    Child 
 
<!-- ko foreach: parentChildData.children --> 
 
    <input type="checkbox" data-bind="checked:isSelected"/> 
 
    <!-- /ko --> 
 
    </div> 
 
    <br/> 
 
    <input type="button" value="Make dependent" data-bind="click:makeDependent"> 
 
    </div>

回答

1

我想這個問題是與在您設置的初始化時發生的事件順序。考慮以下在實施流程 -

  • parentCheckBox首先定義爲self.parentChildDataobservable財產。
  • self.parentChildData.children數組用子項進行初始化。
  • parentCheckBox現在更改爲computed observable

我在這裏看到的問題是,parentCheckBox被要求作出反應self.parentChildData.children給孩子所做的更改,在此之前孩子陣列已經初始化,因此這種依賴未創建這就是爲什麼你沒有得到你期望的行爲。

於是,我改變了你的代碼位的流量和初始化後parentCheckBox被分配的computedObservable作用(雖然它並沒有改變它是如何開始定義)self.parentChildData.children

self.parentChildData.parentCheckBox = ko.computed({ 

read: function() { 
    var anyChildUnChecked = ko.utils.arrayFirst(self.parentChildData.children(), function(childCheckBox) { 
    return !childCheckBox.isSelected(); 
    }); 
    var result = anyChildUnChecked == null; 
    return result; 

    //return false; 
}, 

write: function(value) { 
    ko.utils.arrayForEach(self.parentChildData.children(), function(childCheckBox) { 
    childCheckBox.isSelected(value); 
    }); 
} 
}); 

self.parentChildData.children(childrenArray); //values are pushed here 

此外,這消除了對self.makeDependent功能的需要,雖然它是奇怪,我也說怎麼這個功能能夠使時仍computed以前self.parentChildData.children已經有值創建它的工作: - )

更新fiddle

+0

你在這裏描述的解決方案是完全匹配我的第一個場景工作,我想了解*爲什麼規則3和4不工作時,屬性'self.parentChildData.parentCheckBox'從'Observable 'to'ComputedObservable' **動態**,意思是在某個事件*上發生變化。你描述的場景甚至在模型被綁定到UI之前直接覆蓋屬性,這不是我的場景2. – Agalo

+0

如果我在這裏不清楚,但是當你指向函數self.makeDependent時,請原諒我在這裏提到'某個事件'__意味着某個事件發生了變化___? – gkb

+0

*我的意思是某些事件*是那個函數'self.makeDependent'被觸發爲html中定義的一個點擊' '。所以,點擊只是這個函數可以調用的一種方式。我希望它能清除這個問題。 – Agalo

相關問題