Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

where to write dom manipulation code when using knockout and MVVM

Tags:

knockout.js

im starting to get my head around knockout and if its correct to write code in the viewmodel that manipulates the dom or fires animations etc. As an example i have this binding that passes in a reference to a div which i want to slide out when the tr is clicked

<tr data-bind="click: function(data, event){$parent.Select('#PanelWrapper', $data)}">

In my viewmodel i have

self.Select = function (panel, e) {
        console.log(ko.toJS(e));
        if(self.SelectedEmployee() === e)return;

        self.$PanelWrapper = $(panel);
        var $Bottom = parseInt(self.$PanelWrapper.css("bottom"));

        if($Bottom === 0){
            self.$PanelWrapper.animate({
                bottom:"-95"
            }, 500, function(){
                self.SelectedEmployee(e);
                self.Editable(new Employee(ko.toJS(e)));
            }).animate({
                bottom:"0"
            }, 500);
        }else{
            self.SelectedEmployee(e);
            self.Editable(new Employee(ko.toJS(e)));

            self.$PanelWrapper.animate({
                bottom:"0"
            }, 500);       
        }
    };

Im wondering if this is valid and that it follows the vmmv methodology. Any help would be appreciated

like image 626
Richard Banks Avatar asked Jul 29 '13 15:07

Richard Banks


2 Answers

No, it's not a good idea to manipulate the dom inside your viewmodel. The whole concept of MVVM is to separate the view and the data/behavior part of the UI.

You should use custom binding handlers or you may also create these effects/controls (I don't know what exactly is this) outside your viewmodel. The viewmodel should only model the view: data and commands on that data.

like image 79
Peter Porfy Avatar answered Nov 18 '22 23:11

Peter Porfy


You should't alter directly the dom when you code with knockout.

I suggest to use the slideBinding (jQuery is required).

I made a fiddle to demonstrate how to use it. It's a kind of master/details view.

The view :

<div data-bind="foreach : people">
    <div data-bind="click : $parent.onClick" style="cursor: pointer">
        <span data-bind="text : name"></span>
        <div data-bind="slideVisible: $parent.selected() == $data">
            <span data-bind="text : details"></span>
        </div>
    </div>
</div>

The view model :

var vm = {
    selected: ko.observable(''),
    people : [{
        name: "name1",
        details: "details1"
    }, {
        name: "name2",
        details: "details2"
    }],
    onClick: function (item) {
        vm.selected(item);
    }
};

I hope it helps.

like image 2
Damien Avatar answered Nov 19 '22 00:11

Damien