Steven
Steven

Reputation: 19425

How can I create a Knockout function that is used multiple times on the same page?

I'm still learning Knockout JS and I'm wondering how I can create a "general" view model /function that can be applied to multiple elements on the same page.

A concrete example is where I'm trying to create a global function that slides down / up a HTML element by adding a CSS class. The slide effect is created using CSS transistion.

So far it's working: (jsFiddle):

<button type="button" class="btn btn-primary" data-bind="click: slideInOutClick()"> Show more details </button>

<div class="slide-in-out-container w300" data-bind="css: { 'show200': slideOut() === false }">
    <div class="panel panel-primary">
        <div class="panel-body">
            <p>Some text here</p>
            <p>And some more text here</p>
        </div>

    </div>
</div>

JS:

// Global Knockout model
ko.applyBindings(new globalModel());

function globalModel(){
    var self = this;

    self.slideOut = ko.observable();

    self.slideInOutClick = function(){
        self.slideOut(!self.slideOut());
    }
}

The problem comes when I need multiple sliding panels on the same page. So my question is, how can I use Knockout to achieve this?

Upvotes: 1

Views: 115

Answers (1)

Jeroen
Jeroen

Reputation: 63749

You want to extend Knockout itself, by creating a custom binding handler. The exact example you mention is in that article, albeit with jQuery:

ko.bindingHandlers.slideVisible = {
    update: function(element, valueAccessor, allBindings) {
        // First get the latest data that we're bound to
        var value = valueAccessor();

        // Next, whether or not the supplied model property is observable, get its current value
        var valueUnwrapped = ko.unwrap(value);

        // Grab some more data from another binding property
        var duration = allBindings.get('slideDuration') || 400; // 400ms is default duration unless otherwise specified

        // Now manipulate the DOM element
        if (valueUnwrapped == true)
            $(element).slideDown(duration); // Make the element visible
        else
            $(element).slideUp(duration);   // Make the element invisible
    }
};

For your specific example you could either modify this, or, depending on how you're doing that "CSS Transition", you may be able to get by just using the css binding to toggle the class, and let CSS3 handle the transition.

This allows you to keep your view models (which are close to the business logic) seperate from view concerns such as transitions.

Upvotes: 3

Related Questions