Dynamically apply CSS styles with knockout.js bindings based on conditions

I am looking to apply a conditional css class and a dynamic css class using the css binding feature.

For example:

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

Answer №1

To make it more clear, the best approach would be to consolidate them into a single computed function:

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'">

This approach allows for comprehensive unit testing of the entire functionality while also keeping the view concise and organized.

Answer №2

I personally enjoy using a customized binding method, as shown here:

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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Dealing with an XML file using JavaScript

Is it possible for JavaScript to interact with an XML file fetched using AJAX? I have a server-side XML file and want to fill fields based on its content. Can I simply read "xmlfile.xml" directly from the server, extract values in JavaScript from the res ...

Issue with printing error messages for JavaScript form validation

I have implemented the following code for a form to handle validation and display errors below the fields when they occur: <!DOCTYPE html> <html> <head> <style type="text/css"> .errorcss { background-color: yellow; color:re ...

Customizing the Steps Component in Ant Design

Currently, I am utilizing the Steps component from Ant Design. My goal is to enhance its functionality by adding additional components, like a button placed next to each step's description to make it more interactive. Furthermore, I am looking to inc ...

"Learn how to position a div element below the header div and above the footer div while maintaining full height in

Recently delving into the world of reactjs, I find myself facing a challenge with a page that contains 3 distinct blocks formed by divs. Have a look at the layout on my page: My Page This is the code snippet I have worked on: return ( <div> ...

The battle between Google Visualization API JSON and ArrayToDataTable in Python, a nightmare of data types

Initially, I developed a basic static google visualization page using python The python source code is as follows: def print_graph_script(temp_table): # google chart snippet chart_code=""" <script type="text/javascript" src="https://www.g ...

Access the system by logging in with a stored Google account

I have experience integrating "Login via Google account" on various websites. However, some sites like Zomato always display the option to login via Google as soon as you open them. They even show a list of Google accounts that I have previously logged i ...

Error: Authorization requires both data and salt arguments

As a novice in NodeJS, I attempted to create an authentication form using NodeJS + express. The issue I am facing is regarding password validation - specifically, when "confirmpassword" does not match "password", it should return nothing. Despite my effo ...

Utilize the three.js library within a Vue component by importing it and incorporating its

Can someone please help me understand the proper way to import and utilize the three.js library in a vue component? Despite my extensive research, it seems that most individuals use the following code line to import three.js into a vue component. However, ...

Display logo when website has been scrolled

On my website, I want to display a logo in the header only when the site has been scrolled. I attempted to accomplish this with JavaScript: if(document.getElementById("div").scrollTop != 0){ document.write("<img src='logo.jpg'>"); } How ...

the click event fails to trigger when the id or class is modified

Hey there, I'm new to working with jquery and I've encountered a problem. Here's the code snippet: http://jsfiddle.net/8guzD/ $('#test.off').click(function(){ $(this).removeClass('off').addClass('on'); }) ...

Exploring the possibilities of integrating Keycloak with the powerful nuxt-auth

I am incorporating this particular authentication module in conjunction with Keycloak. In my nuxt.config.js configuration: keycloak: { _scheme: 'oauth2', client_id: 'client-bo', userinfo_endpoint: 'SERVER/protocol/open ...

Fetching URL from Right Before Logging Out in Angular 2 Application

I am struggling to capture the last active URL before logging a user out of my Angular 2 app. My goal is to redirect them back to the same component or page once they log back in. Currently, I am using this.router.routerState.snapshot['url'] to r ...

Error importing reach-router in Gatsbyjs causing website to break

While working on my Gatsby project, I decided to incorporate the React Cookie Consent package. However, upon installation and implementation attempt, my website crashed, displaying this error message: warn ./.cache/root.js Attempted import error: &a ...

Exploring the beauty of semicolons within ES6

In my understanding, semicolons were supposed to be outdated with the introduction of ES6. However, I stumbled upon this today: Doesn't seem to work as expected: let i = 0 [0, 1, 2, 3, 4, 5, 6].forEach(item => console.log(item)) But it works wh ...

Navigate to the top of the Vue scrollable list using v-auto-complete

I need to implement a feature that automatically scrolls to the top of a scrollable list every time the search input is changed. Currently, I have a list where multiple items can be selected, and I want it to reset to the top whenever a new search query is ...

Tips for inserting information from a JSON file into a mailto hyperlink

As a newcomer to JavaScript, I am eager to tackle the challenge presented below: Situation: In possession of a JSON file containing personal details such as name, email address, bio, etc., my task is to design a basic web page showcasing this data for ea ...

The 'v-model' directive necessitates a valid attribute value for the left-hand side (LHS)

I am facing an issue with my Vue application. I have a table where each row has its own unique id. I need to show or hide certain elements based on a condition in the v-model directive which compares the row id with a value in the model. The current code s ...

What is the best way to verify Vue.js fields that have been pre-filled from a database source?

Looking to validate the inputs from a form using vuejs. Also, if the data is pre-populated, I want the inputs to switch to readonly mode. <input type="number" name="cf_962" class="form-control" v-model="fillProfile.cf_962" step="0.1" :readonly="(fillPr ...

I'm noticing that my CSS is behaving differently than expected. Despite setting position: absolute, the output is displaying as inline-block instead of block. Why is this happening

div { width:200px; height:200px; position: absolute; } .first-container { background-color: #9AD0EC; } .second-container { background-color: red; left: 200px; } .third-container { background-color: blue; left:400px; } Despite setting th ...

Retrieve all node names from a .dae file using three.js

When I import a collada file into my scene, I am trying to figure out how to list all the node names. Can anyone help me with this? Here is what I have tried so far, but it only gives me one name: var dae; loader.options.convertUpAxis = true; loader.load ...