Asynchronous
Asynchronous

Reputation: 3977

How to toggle css class on a table head which also has an existing click binding?

I am attempting to toggle css class on a table head. However, the table header already has a click binding: I referenced the docs here:

I need to have a class on the table head (thead) by default and then add/remove (toggle) the class when the head is clicked. The goal is to use the class to add visual descriptions to the table head which are sortable:

Here is the code below doing the sorting: NOTE: This code and idea was copied from Ryan Rahlf blog. Article here:

I am thinking the css binding can be called from the sort function so that it is applied or removed from column head as they are clicked:

    self.sort = function(header, event){

        // This is the existing click binding (sort)
        // Place css logic in here so that individual thead class is toggled when clicked.

        if(self.activeSort === header) {

            header.asc = !header.asc;

        } else {
            self.activeSort = header;
        }

        var prop = self.activeSort.sortPropertyName;
        var ascSort = function(a,b){ return a[prop] < b[prop] ? -1 : a[prop] > b[prop] ? 1 : a[prop] == b[prop] ? 0 : 0; };
        var descSort = function(a,b){ return a[prop] > b[prop] ? -1 : a[prop] < b[prop] ? 1 : a[prop] == b[prop] ? 0 : 0; };
        var sortFunc = self.activeSort.asc ? ascSort : descSort;
        self.Artist.sort(sortFunc);
    };

Example on JSfiddle:

Upvotes: 2

Views: 291

Answers (1)

Joel R Michaliszen
Joel R Michaliszen

Reputation: 4222

there are many approach to do this, but to not change many things what you do here, see the snippet one of the approach:

function viewModel() {

        var self = this;
        
        self.orderedBy = ko.observableArray([]);
        
        self.Artist = ko.observableArray([
            {
                'LastName': 'Simon',
                'FirstName': 'Paul'
            }
            ,
            {
                'LastName': 'McCartney',
                'FirstName': 'Paul'
            },
            {
                'LastName': 'McKnight',
                'FirstName': 'Brian'
            },
            {
                'LastName': 'Morrison',
                'FirstName': 'Marc'
            }]);

        self.headers = [
            {title: 'First Name', sortPropertyName: 'FirstName', asc: true},
            {title: 'Last Name', sortPropertyName:  'LastName', asc:true}
        ];

        self.sort = function(header, event){          
          
          self.activeSort = header;  
          
          if(self.orderedBy.indexOf(header.title)>=0)
            self.orderedBy.remove(header.title);          
          else
            self.orderedBy.push(header.title);
          
          self.activeSort.asc = !self.activeSort.asc;
          var prop = self.activeSort.sortPropertyName;
          var ascSort = function(a,b){ return a[prop] < b[prop] ? -1 : a[prop] > b[prop] ? 1 : a[prop] == b[prop] ? 0 : 0; };
          var descSort = function(a,b){ return a[prop] > b[prop] ? -1 : a[prop] < b[prop] ? 1 : a[prop] == b[prop] ? 0 : 0; };
          var sortFunc = self.activeSort.asc ? ascSort : descSort;
          self.Artist.sort(sortFunc);
        };
    }

    ko.applyBindings(viewModel());
.ordered{
  background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <table>
        <thead>
        <tr data-bind="foreach: headers">
            <th data-bind="click: sort, text: title, css:{ordered: orderedBy.indexOf(title)>=0}"></th>
        </tr>
        </thead>

        <tbody data-bind="foreach: Artist">
        <tr>
            <td data-bind="text: FirstName"></td>
            <td data-bind="text: LastName"></td>
        </tr>
        </tbody>
    </table>

Hope be useful.

Upvotes: 2

Related Questions