Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout.js show / hide block visibility pattern

I have the code duplication problem in the next case. On my page I have a lot of blocks that I need to show / hide by clicking to link:

<div>
    <a data-bind="click: showHiddenFirst, visible: isVisibleFirst"href="#">Show first</a>
    <div data-bind="visible: !isVisibleFirst()" style="display:none">
        hidden content first
    </div>
</div>
<div>
    <a data-bind="click: showHiddenSecond, visible: isVisibleSecond"href="#">Show second</a>
    <div data-bind="visible: !isVisibleSecond()" style="display:none">
        hidden content second
    </div>
</div>

And my JS

var vm = function(){
    this.isVisibleFirst = ko.observable(true);

    this.showHiddenFirst = function(){
        this.isVisibleFirst(false)
    };

    this.isVisibleSecond = ko.observable(true);

    this.showHiddenSecond = function(){
        this.isVisibleSecond(false)
    };
};

ko.applyBindings(new vm());

Here is jsfiddle example http://jsfiddle.net/sstude/brCT9/2/

Question is how to avoid all this show / visible duplication? Maybe I need some custom binding where I put id of my hidden block or smth. else? Any patterns that you can suggest?

like image 492
Akim Khalilov Avatar asked Feb 18 '13 09:02

Akim Khalilov


People also ask

How do you get the Knockout value from observable?

To read the observable's current value, just call the observable with no parameters. In this example, myViewModel. personName() will return 'Bob' , and myViewModel. personAge() will return 123 .

What is $data in Knockout?

The $data variable is a built-in variable used to refer to the current object being bound. In the example this is the one of the elements in the viewModel.

What is applyBindings in Knockout?

To apply bindings for the whole HTML document, it can be done using the Knockout function applyBindings() with passing the view model as the first and the only parameter: ko. applyBindings(viewModel); To apply Knockout for a part of the HTML document, pass the DOM element as a second parameter: ko.

What is Ko observable in knockout JS?

Knockout. js defines an important role when we want to detect and respond to changes on one object, we uses the observable. An observable is useful in various scenarios where we are displaying or editing multiple values and require repeated sections of the UI to appear and disappear as items are inserted and deleted.


1 Answers

Here was a thought at encapsulating this functionality completely in an observable for your specific scenario:

ko.bindingHandlers.clickVisible = {
    init: function(element) {
       var visible = ko.observable(true),
           opposite = ko.computed(function() { return !visible(); }),
           clickHandler = visible.bind(null, false);

        //apply bindings to anchor
        ko.applyBindingsToNode(element, { click: clickHandler, visible: visible });

        var sibling = element.nextSibling;
        //find the div (as text nodes, etc. will show up in nextSibling)
        while (sibling && sibling.nodeType != 1) {
            sibling = sibling.nextSibling;   
        }        

        //apply bindings to div
        if (sibling) {
            ko.applyBindingsToNode(sibling, { visible: opposite });
        }
    }
};

It could be tweaked further, as necessary, if maybe the value passed into the binding should matter.

Example: http://jsfiddle.net/rniemeyer/gCgy5/

like image 164
RP Niemeyer Avatar answered Nov 15 '22 09:11

RP Niemeyer