Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery UI tab init after array change in knockoutjs

From what I have done in past(before using knockoutjs) I would call the tabs() function anytime I updated the view on a page. I'm trying to do this on a knockoutjs page I have done. Everytime I change the observable array it de-initializes the jquery tabs. That's fine I'll just call the function. This doesn't seem to do anything.

    var viewModel = {       

    lines: ko.observableArray([]),      
    activeTab: ko.observable(),         
    addLine : function() {  

        var self = this;            
        $.post('/add/line', {customer_id : customer_id } , function(data) {                 
            var line = ko.toJS(data);               
            self.lines.push(new Line(line.id, line.name, line.equipType, line.model, line.height, line.length, line.loadsWeek, line.weight, line.width, line.pallets));

            $("#lineTabs").tabs({ selected: 0 });
            $(".palletTabs").tabs({ selected: 0 });             
        });     
    }
};

For some reason it works fine when I'm initializing the page.

$.getJSON("/json/all/lines", { customer_id : customer_id } , function(data) {       

        var mappedData = ko.utils.arrayMap(data, function(line) {               
            return new Line(line.id, line.name, line.equipType, line.model, line.height, line.length, line.loadsWeek, line.weight, line.width, line.pallets)        
        });

        viewModel.lines(mappedData);        

        $("#lineTabs").tabs({ selected: lineTabIndex });
        $(".palletTabs").tabs({ selected: 0 });

    }); 

Is there something I'm missing here? Thanks for any help.

like image 967
Drew H Avatar asked Nov 08 '11 20:11

Drew H


1 Answers

The roadmap for jQuery UI tabs shows that they are going to add a refresh method that would make this easier.

When I have combined KO with jQuery UI tabs, I have relied on destroying and reinitializing the tabs whenever my observableArray changes.

I use a custom binding to do this like:

ko.bindingHandlers.jqTabs = {
    update: function(element, valueAccessor, allBindingsAccessor) {
       var dependency = ko.utils.unwrapObservable(valueAccessor()),
           currentIndex = $(element).tabs("option", "selected") || 0,
           config = ko.utils.unwrapObservable(allBindingsAccessor().jqTabOptions) || {};

        //make sure that elements are set from template before calling tabs API
        setTimeout(function() { 
            $(element).tabs("destroy").tabs(config).tabs("option", "selected", currentIndex);
       }, 0);
    }
};

When you use the binding, you would pass your observableArray to it. Optionally, you can pass config options for the tabs in the jqTabOptions additional binding. The binding does try to reset the selected index back to where it started when recreating it. Based on your code, you might not want to do this part.

Here is a sample: http://jsfiddle.net/rniemeyer/rcqT4/

like image 57
RP Niemeyer Avatar answered Nov 11 '22 08:11

RP Niemeyer