How to dynamically assign classes to a group of radio buttons based on their current state using ReactJS

I've been attempting to dynamically assign classes to radio buttons, but I'm facing difficulties in doing so. I'm trying to create a switch with radio buttons for "ENABLED, PENDING, DISABLED". Based on the selected radio button, I want to change the color by assigning class names. Any assistance on this issue would be greatly appreciated.

For reference, you can view my sandbox at: https://codesandbox.io/s/complex-logic-to-map-an-array-rkspo

App


import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      switchValue: "pending"
    };
    this.handleButtonChange = this.handleButtonChange.bind(this);
  }

  handleButtonChange(event) {
    this.setState(
      {
        switchValue: event.target.value
      },
      () => {
        console.log(this.state.switchValue);
      }
    );
  }

  render() {
    const { switchValue } = this.state;
    return (
      <div className={"switch-toggle"}>
        <input
          type="radio"
          onChange={this.handleButtonChange}
          name={"disabled"}
          value={"disabled"}
          checked={switchValue === "disabled" ? true : false}
        />{" "}
        <label className={switchValue === "disabled" ? "switch-red" : ""}>
          DISABLED
        </label>
        <input
          type="radio"
          onChange={this.handleButtonChange}
          name={"pending"}
          value={"pending"}
          checked={switchValue === "pending" ? true : false}
        />{" "}
        <label className={switchValue === "pending" ? "switch-pending" : ""}>
          PENDING
        </label>
        <input
          type="radio"
          onChange={this.handleButtonChange}
          name={"enabled"}
          value={"enabled"}
          checked={switchValue === "enabled" ? true : false}
        />{" "}
        <label className={switchValue === "enabled" ? "switch-green" : ""}>
          ENABLED
        </label>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

CSS

.switch-toggle {
  float: left;
  background: #242729;
}
.switch-toggle input {
  position: absolute;
  opacity: 0;
}
.switch-toggle input + label {
  padding: 7px;
  float: left;
  color: #fff;
  cursor: pointer;
}
.switch-pending {
  background: grey;
}
.switch-disabled {
  background: red;
}
.switch-enabled {
  background: green;
}

Answer №1

Check out this modified version of your sandbox with the functional code: https://codesandbox.io/s/complex-logic-to-map-an-array-8ghfh

Always keep track of the classes you are utilizing.

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      switchValue: "pending"
    };
    this.handleButtonChange = this.handleButtonChange.bind(this);
  }

  handleButtonChange(event) {
    this.setState(
      {
        switchValue: event.target.value
      },
      () => {
        console.log(this.state.switchValue);
      }
    );
  }

  render() {
    const { switchValue } = this.state;
    return (
      <div className={"switch-toggle"}>
        <input
          id="disabled"
          type="radio"
          onChange={this.handleButtonChange}
          name={"disabled"}
          value={"disabled"}
          checked={switchValue === "disabled" ? true : false}
        />{" "}
        <label
          htmlFor="disabled"
          className={switchValue === "disabled" ? "switch-disabled" : ""}
        >
          DISABLED
        </label>
        <input
          id="pending"
          type="radio"
          onChange={this.handleButtonChange}
          name={"pending"}
          value={"pending"}
          checked={switchValue === "pending" ? true : false}
        />{" "}
        <label
          className={switchValue === "pending" ? "switch-pending" : ""}
          htmlFor="pending"
        >
          PENDING
        </label>
        <input
          id="enabled"
          type="radio"
          onChange={this.handleButtonChange}
          name={"enabled"}
          value={"enabled"}
          checked={switchValue === "enabled" ? true : false}
        />{" "}
        <label
          htmlFor="enabled"
          className={switchValue === "enabled" ? "switch-enabled" : ""}
        >
          ENABLED
        </label>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

However, using radio buttons may not be the best choice as they are not visible in this particular scenario. Using standard buttons with click events could be a better approach, resulting in cleaner markup :)

You can achieve the same functionality with a simpler structure like this: https://codesandbox.io/s/complex-logic-to-map-an-array-w6hgb

Answer №2

There appears to be a disconnect between the label and the input field, as clicking on the label does not trigger any action:

To resolve this issue, you can adjust the code as follows:

<input type="radio" id="foo" />
<label htmlFor="foo">Foo</label>

Alternatively, you can use the following structure:

<label>
 <input .../>
</label>

Additionally, it seems that the CSS class is named switch-enabled but you have set it as switch-green, which will not produce the desired effect :)

Take a look at the radio group documentation:

To create a radio group, assign the same name to each radio button within the group. When one radio button is selected, any previously selected radio button in the same group will be deselected automatically.

A cleaner and more semantically correct example could be structured like this:

function RadioGroup({ defaultChecked = "bar" }) {
  function handleChange(ev) {
    const { value } = ev.target;
    // handle the value here
  }

  return (
    <form>
      <label>
        <input
          defaultChecked={defaultChecked === "foo"}
          type="radio"
          name="name"
          value="foo"
          onChange={handleChange}
        />{" "}
        Foo
      </label>

      <label>
        <input
          defaultChecked={defaultChecked === "bar"}
          type="radio"
          name="name"
          value="bar"
          onChange={handleChange}
        />{" "}
        Bar
      </label>

      <label>
        <input
          defaultChecked={defaultChecked === "baz"}
          type="radio"
          name="name"
          value="baz"
          onChange={handleChange}
        />{" "}
        Baz
      </label>
    </form>
  );
}

If your HTML Markup is correct, you may utilize the CSS Pseudo Selector "checked" to style your CSS without JavaScript 🎉

Furthermore, you can refer to the answer provided by Christopher for a solution to your specific issue, with this as an additional suggestion.

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

Missing RequestVerificationToken value when hiding HTML element using jQuery

I am encountering an issue with my ASP.NET MVC 4 form that involves checkboxes being used to show and hide certain HTML elements. When I initially visit the form page, the RequestVerificationToken value is correctly created as a hidden field. Some HTML ele ...

Launch your React JS website on GitHub Pages

Recently, I successfully developed my first React JS application by utilizing the create-react-app command line tool. Prior to executing npm run build However, upon attempting to access the GitHub page at username.github.io/project-name/public, a 404 err ...

What is the best way to align the middle item of a flexbox using CSS?

I am attempting to present text divided into 3 divs - the middle div contains the highlighted portion of the text, while the first and last divs contain the text before and after the highlighted section. Both the first and last flex items have classes tha ...

What is the best way to store my JSON output in a JavaScript variable?

In my jsonOutput.php page, the code looks like this: $response['imgsrc'] = $filename[1]; echo json_encode($response); When executed, it produces a JSON output like {"imgsrc":"071112164139.jpg"} My query now is, how can I make use of ...

Error message: "npm start cannot locate package.json file, even though the file is present

As I attempt to execute npm start within my Node.js project directory, I am facing a challenge. Despite having the package.json file in the correct location (C:\Myfirstproject\Vinci\Projet_Web), I keep encountering an error message that read ...

Guide on replacing buttons with <a> tags in express.js posts

I've incorporated handlebars as my chosen templating engine and I'm utilizing buttons to trigger app.post() in my JavaScript file. <form method="POST" action="/smo_assessment"> <div class="container" id="div1"> <h3 id="header" ...

What is the best way to create a header similar to the one in the image using only CSS

Wondering if it's possible to create a header like the one in the image using just pure CSS and without Photoshop. How can I design it in a professional manner? You can view an example of the image here. ...

Utilizing cylon.js with Nest Thermostat

Experiencing errors while trying to retrieve thermostat ambient Temperature with cylon.js I have already replaced ACCESS_TOKEN with my unique access token and device id Sample Code: var Cylon = require('cylon'); Cylon.robot({ connections: { ...

Display all months vertically with Bootstrap-Year-Calendar instead of horizontally

I recently integrated the Bootstrap-Year-Calendar plug-in into my project, but it seems to be displaying vertically. I'm not sure if this issue is related to my scripts or links. I attempted to change the versions of both jQuery and Bootstrap, but the ...

Enhancing Drag and Drop Functionality with jQuery and CSS Zoom Effect

I am facing an issue in my application with a div that has variable CSS zoom. Due to this, the coordinate space gets disrupted. The page pixel is no longer equal to 1px when hovering over the zoomable area :) This breakdown in the coordinate system is ca ...

Is XPath applicable to data that has been labeled?

I am looking to access the data within the second div: <div class="my-3"> <div class="d-flex justify-content-between">Monthly:</div> <div>0 / 30,000</div> </div> Within the code above, I want to t ...

What is the method to customize the color of the Stepper component in React Material UI?

https://i.sstatic.net/axn1Z.png The image shows my attempt to modify the step color based on its status: green for correct, yellow for in-progress, and red for incorrect. Can anyone guide me on how to achieve this? ...

Adding and removing dynamic fields with Bootstrap functionality

Recently, I've been trying to develop a feature where users can add and remove fields by clicking on a button. However, I've encountered a roadblock in my progress. If you take a look at this CodePen link, you'll see what I have so far. My a ...

What is the proper way to designate a manifest.json link tag on a limited-access website controlled by Apache shibboleth?

The issue arises when attempting to access the manifest.json file. It has been declared as follows: <link href="manifest.json" rel="manifest"/> Is it possible to declare the manifest tag inline, or what would be the most effective way to declare it ...

Utilizing UTC Time with AngularUI's UI-Date Datepicker

My issue lies with the datepicker using localized time instead of UTC when making calls to the backend. To handle this, I've created a function that adjusts the value before posting it to the server: function adjustDateForTimeOffset(dateToAdjust) ...

Showing the output variable from node.js on a canvas

Is it possible to display the output of my node.js program, which consists of a series of points (x,y), on canvas without a browser? I came across this module that could potentially help with displaying the points: (https://www.npmjs.com/package/canvas) ...

jQuery animation for expanding accordion headers

I want to create a cool animation for my accordion headers that mimics a ribbon being dragged onto the wrapper when hovered over, and then dragged out when the hover ends. Everything was working fine in this initial jsFiddle, but as soon as I tried to ani ...

How can you utilize a previously opened window from another page in JavaScript?

One of my challenges involves managing windows in a JavaScript environment. When I open a child window using window.open("http://foobar","name"), it reuses the same window when opened with the same name, which is exactly what I want. However, if the origi ...

Performing an AJAX request from a subfolder

Can anyone help me figure out how to make an ajax request from a page located in a subdirectory and receive a response? On my webpage, index.jsp is situated within a subdirectory called /vf2. In this page, there is a script file included: <script src=" ...

Issue with MUI Grid item not functioning properly when using overflowY: "auto"

I am encountering an issue while using MUI with React. I have a <Paper> element wrapping a <Grid> with 3 children elements. The problem arises when I set the overflowY property of the bottom grid item to "auto" - instead of showing the scroll b ...