Corey Sutton
Corey Sutton

Reputation: 1015

Adding multiple CSS Elements to a data-bind with Knockout

I need to add multiple css classes to a div using knockout.

I have this div:

    <div data-bind="css: {'case-header': model.caseHeader1, 'case-type-1': model.caseHeader2, 'case-type-2': model.caseHeader3}">

the model.caseHeader1 is the default. caseHeader2/3 are only true when the conditions are met. Our design engineer informed me that the css class 'case-header' needs to be on all three and add the css classes 'case-type-1/2' along side 'case-header'.

So I did this:

    <div data-bind="css: {'case-header': model.caseHeader1, 'case-header case-type-1': model.caseHeader2, 'case-header case-type-2': model.caseHeader3}">

Now one of the model types in the UI shows correctly, the other only shows case-type-1/2.

I also tried this:

    <div data-bind="class: 'case-header', css: {'case-header': model.caseHeader1, 'case-header case-type-1': model.caseHeader2, 'case-header case-type-2': model.caseHeader3}">

and this:

    <div class="case-header" data-bind="css: {'case-header': model.caseHeader1, 'case-header case-type-1': model.caseHeader2, 'case-header case-type-2': model.caseHeader3}">

Which did not work, unfortunately.

In case it is needed, here is the relevant typescript:

self.model.caseHeader1 = ko.computed(function () {
        return !self.model.useColorHeaderCaseHistory(); //a true false boolean that returns true if the client is using it, in this case, it is true
    });

    self.model.caseHeader2 = ko.computed(function () {
        return self.model.isRatingCase() && self.model.useColorHeaderCaseHistory();
    });

    self.model.caseHeader3 = ko.computed(function () {
        return self.model.isQiCase() && self.model.useColorHeaderCaseHistory();
    });

Upvotes: 1

Views: 73

Answers (2)

Martlark
Martlark

Reputation: 14581

A more effective way to handle classes for an element is to use a computed for the class binding. Example:

HTML:

<div data-bind="class: caseClasses">What class am I?: <span data-bind="text: caseClasses"></span></div>

Model computed method:

  this.caseClasses = ko.computed(() => {
    const classes = [];

    if (!this.useColorHeaderCaseHistory()) {
      classes.push('caseHeader1')
    } else {
      if (this.isRatingCase()) classes.push('caseHeader2');

      if (this.isQiCase()) classes.push('caseHeader3');
    }
    return classes.join(' ');
  });

Please see this js fiddle with a working example: knockout class binding

Upvotes: 0

Corey Sutton
Corey Sutton

Reputation: 1015

I made this very difficult. When I considered that all of the models needed the css class 'case-header' regardless, I just wrapped it in another div:

div class="case-header">
        <div data-bind="css: {'case-header': model.caseHeader1, 'case-type-1': model.caseHeader2, 'case-type-2': model.caseHeader3}">
</div>
</div>

solved all of my problems. Now I am pretty sure I don't need to bother with the first check in the data-bind either.

Upvotes: 0

Related Questions