Thargor
Thargor

Reputation: 729

knockout, css binding dynamic and conditional

I wan't to have a conditional css class and a dynamic css class added via the css binding.

Like so:

data-bind="css: {$data.something() : true, open : showOpen()  }"

Upvotes: 1

Views: 716

Answers (2)

DonSteep
DonSteep

Reputation: 1075

I prefer a custom binding like this:

ko.bindingHandlers.klass = {
  init: function (el, val) {
    var prevClass = null
   
    ko.computed(function () {
      if (prevClass)
        $(el).removeClass(prevClass);
      
      var newClass = ko.unwrap(val());
      
      $(el).addClass(newClass);
      prevClass = newClass;
    }, null, {disposeWhenNodeIsRemoved: el})
    
  }
}

var vmo = {
  cssClass: ko.observable('a'),
  toggle: function () { vmo.cssClass(vmo.cssClass() == 'a' ? 'b' : 'a') }
}

ko.applyBindings(vmo);
.a {
  color: red;
}
.b {
  color: blue;
}
.another {
  text-decoration: underline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<p data-bind='klass: cssClass, css: {another: true}'>Hello</p>
<button data-bind='click: toggle'>Toggle</button>

Upvotes: 0

Jeroen
Jeroen

Reputation: 63699

Clearest is probably to combine them in one computed:

function ViewModel() {
  var self = this;
  
  self.something = ko.observable("danger");
  self.showOpen = ko.observable(true);
  
  self.cssClass = ko.computed(function() {
    return self.something() + (self.showOpen() ? " open" : "");
  });
}

ko.applyBindings(new ViewModel());
div { padding: 10px; }
.danger { background-color: orange; }
.open { border: 5px solid gray; border-width: 5px 5px 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>

<div data-bind="css: cssClass"> my div with class: <code data-bind="text: cssClass"></code> </div>
<hr>
<label><input type="checkbox" data-bind="checked: showOpen"> showOpen</label>
<br>
<input type="text" data-bind="value: something, valueUpdate: 'afterkeydown'">

Allows you to unit test the entire thing, and keeps your view concise.

Upvotes: 1

Related Questions