Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockoutjs: can we create a dependentObservable function with a parameter?

Tags:

knockout.js

I have multiple input boxes that I want to hide/unhide based on a selection from user.

I can achieve this by having a separate dependentObservable for each input and in turn making the dependentObservable observe the parent selection.

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
);

this is kind of tedious to do for each field. Can I bind the elements with a dependentObservable function that can take a parameter? Important thing is it should get triggered when the parent changes

Other option is that when the parent changes, I loop through the elements and hide/unhide but that will require me to map the element id <-> business name of the field.

Current

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

Desired

<tr data-bind="visible: showField('BusinessFieldName1')">
<tr data-bind="visible: showField('BusinessFieldName2')">
like image 832
Pinakin Shah Avatar asked Jul 15 '11 11:07

Pinakin Shah


People also ask

Which function is used to perform Knockout computation?

Determining if a property is a computed observable Knockout provides a utility function, ko.

How do you activate a Knockoutjs model?

To activate Knockout, add the following line to a <script> block: ko. applyBindings(myViewModel); You can either put the script block at the bottom of your HTML document, or you can put it at the top and wrap the contents in a DOM-ready handler such as jQuery's $ function.

What is Ko observable ()?

Observable arrays combine the power of Knockout. js' observables with native JavaScript arrays. Like native arrays, they contain lists of items that you can manipulate. But since they're observable, Knockout. js automatically updates any associated HTML elements whenever items are added or removed.


2 Answers

In Knockout, bindings are implemented internally using dependentObservables, so you can actually use a plain function in place of a dependentObservable in your bindings. The binding will run your function inside of a dependentObservable, so any observables that have their value accessed will create a dependency (your binding will fire again when it changes).

Here is a sample: 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);
like image 167
RP Niemeyer Avatar answered Sep 27 '22 13:09

RP Niemeyer


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

You can create a function like the one above. The function returns a new dependent observable for the specific field name.

Now you can do:

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

Inform me if that code doesn't work - maybe I missed something. Then I'll edit this post.

like image 36
Arxisos Avatar answered Sep 28 '22 13:09

Arxisos