2011-07-15 8 views
23

Mam wiele pól wejściowych, które chcę ukryć/odkryć na podstawie wyboru użytkownika.knockoutjs: czy możemy utworzyć funkcję dependent zależnie z parametrem?

Mogę to osiągnąć przez posiadanie osobnego obiektu dependObservable dla każdego wejścia, co z kolei powoduje, że obiekt dependent stanie się rodzicem.

viewModel.showField1= ko.dependentObservable(function() { 
    return viewModel.selectedType() ? IsFeatureVisible(viewModel, "BusinessFieldName1") : false; 
}, viewModel 
); 

viewModel.showField1= ko.dependentObservable(function() { 
    return viewModel.selectedType() ? IsFeatureVisible(viewModel, "BusinessFieldName2") : false; 
}, viewModel 
); 

jest to nużące zadanie dla każdego pola. Czy mogę powiązać elementy z funkcją dependObservable, która może przyjąć parametr? Ważną rzeczą jest, że powinien on zostać wywołany, kiedy rodzic zmieni jedną z opcji, gdy zmieni się rodzic, przechodzę przez elementy i ukrywam/odkrywam, ale to wymaga ode mnie zmapowania identyfikatora elementu. < -> nazwa firmy pole.

Aktualny

<tr data-bind="visible: showField1"> 
<tr data-bind="visible: showField2"> 

Pożądany

<tr data-bind="visible: showField('BusinessFieldName1')"> 
<tr data-bind="visible: showField('BusinessFieldName2')"> 

Odpowiedz

31

W Knockout powiązania są implementowane wewnętrznie za pomocą dependObservables, więc w rzeczywistości możesz użyć zwykłej funkcji zamiast dependObservable w twoich powiązaniach. Wiązanie uruchomi twoją funkcję wewnątrz dependObservable, więc wszelkie obserwowalne, które mają dostęp do ich wartości, stworzą zależność (twoje powiązanie zostanie ponownie uruchomione, gdy się zmieni).

Oto przykład: http://jsfiddle.net/rniemeyer/2pB9Y/

html

type "one", "two", or "three": <input data-bind="value: text" /> 
<hr /> 
<ul data-bind="template: { name: 'itemTmpl', foreach: items }"></ul> 

js

<script id="itemTmpl" type="text/html"> 
    <li data-bind="text: name, visible: viewModel.shouldThisBeVisible(name)"></li> 
</script> 

var viewModel = { 
    text: ko.observable("one"), 
    items: [{name: "one"}, {name: "two"}, {name: "three"}], 
}; 

viewModel.shouldThisBeVisible = function(name) { 
    return this.text() === name; 
}.bind(viewModel); 

ko.applyBindings(viewModel); 
+0

dziękuję. To działało pięknie. Uratowałeś mi dużo czasu. –

+2

Wystarczy notatkę, aby zaktualizować każdego, kto przychodzi. W nowszych wersjach nokautu nie ma potrzeby używania "szablonu" w tym przypadku, możesz po prostu użyć 'foreach'.Widziałem programistów używających 'szablonu', ponieważ oni tego nie rozumieją. Nie ma nic wyjątkowego w powiązaniu z szablonem, które to umożliwia. –

12
var someOtherViewModel = { 
    showField: function(fieldName) { 
     return ko.dependentObservable(function() { 
      return viewModel.selectedType() ? IsFeatureVisible(viewModel, fieldName) : false; 
     }, viewModel); 
    } 
}; 

Można utworzyć funkcję, jak ten powyżej. Funkcja zwraca nową zależną obserwowalną dla konkretnej nazwy pola.

Teraz można zrobić:

<tr data-bind="visible: someOtherViewModel.showField('Field1')"> 

Powiadom mnie jeśli kod nie działa - może coś mi umknęło. Potem zmienię ten wpis.

+0

który wygląda świetnie. Spróbuję. –

+0

Działa jak czar, dzięki! –

+0

To jest fajne, chociaż myślę, że musisz być ostrożny przy użyciu tego. Powiedzmy, jeśli wywołujesz showField w pętli z setkami rekordów, zasadniczo tworzysz 100 dependObservables w pamięci. W takim przypadku lepiej byłoby po prostu zdefiniować showFieldX, showFieldY itd. W swojej maszynie wirtualnej, ponieważ nie są one w 100-tkach, aby utrzymać niski ślad pamięci po stronie klienta. – jesal

0

biorąc pomysł z @Arxisos nawet dalej, wpadłem na to.

self.showField = function (fieldName) 
{ 
    return ko.dependentObservable(function() 
    { 
     return this.selectedType() ? IsFeatureVisible(this, fieldName) : false; 
    }, this)(); 
}; 
Powiązane problemy