简体   繁体   English

以编程方式添加/删除材质ui生成的类

[英]Programatically add/remove class generated by material ui

How can I programmatically add/ remove the material-UI classes that I defined in makeStyles() Here's my code: 如何以编程方式添加/删除我在makeStyles()定义的material-UI类,这是我的代码:

import React from 'react';
import { DropboxIcon, GoogleDriveIcon, BoxIcon } from '../components/icons';
import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles(theme => ({
    input: {
        display: 'none'
    },
    label: {
        display: 'inline-flex',
        marginRight: theme.spacing(2),
        marginLeft: theme.spacing(2),
        justifyCOntent: 'space-between',
        padding: theme.spacing(1, 1.5)
    },
    iconName: {
        marginLeft: theme.spacing(1)
    },
    iconsFormWrapper: {
        marginTop: theme.spacing(2)
    },
    selectedService: {
        backgroundColor: theme.palette.primary.dark,
        borderRadius: theme.spacing(1),
        color: '#ffffff',
        '& svg, img': {
            fill: '#ffffff!important',
            filter: 'brightness(0) invert(1)'
        }
    }

}));

const selectServiceHandle = (e) => {
    const optionName = document.getElementsByName("signup-service");
    optionName.classList.remove("selectedService")
    document.querySelectorAll(`input[value=${e.target.value}]`).classList.add("selectedService")
}

const SignupRadioIcons = () => {
    const classes = useStyles();
        return (
            <div className={classes.iconsFormWrapper}>
                <form>
                    <label className={`${classes.label} ${classes.selectedService}`}>
                         <DropboxIcon/> <span className={classes.iconName}>Dropbox</span>
                          <input type="radio" onChange={(e)=>selectServiceHandle(e)} name="signup-service" value="dropbox" className={classes.input} /> 
                    </label>
                    <label className={classes.label}>
                         <GoogleDriveIcon/> <span className={classes.iconName}>Google Drive</span>
                          <input type="radio" onChange={(e)=>selectServiceHandle(e)} name="signup-service" value="drive" className={classes.input} /> 
                    </label>
                    <label className={classes.label}>
                         <BoxIcon/> <span className={classes.iconName}>Box</span>
                          <input type="radio" onChange={(e)=>selectServiceHandle(e)} name="signup-service" value="box" className={classes.input} /> 
                    </label>
                </form>
            </div>
        )
}


export default SignupRadioIcons;

In my code, I defined a class called selectedService in my makeStyles() But I want to add/remove this class on every change event, Whenever a user click any input I want to remove this class from all other inputs and add it to the one where the user clicked. 在我的代码中,我在makeStyles()定义了一个名为selectedService的类,但是我想在每个change事件上添加/删除该类,每当用户单击任何输入时,我都希望从所有其他输入中删除该类并将其添加到用户点击的位置之一。 But this code is not working because the actual classes that is generated by material UI look like makeStyles-selectedService-224 and the postfix number keeps on changing on every refresh. 但是此代码不起作用,因为由材质UI生成的实际类看起来像makeStyles-selectedService-224并且每次刷新后后缀号都会不断变化。

Given you are using React, I'd suggest you use local state to determine when to apply the class 鉴于您正在使用React,建议您使用本地状态来确定何时应用该类

import React, { useState } from 'react';
const storageProviders = {
  Dropbox: 1,
  GoogleDrive: 2,
  Box: 3
};
...
const SignupRadioIcons = () => {
  const classes = useStyles();
  const [focusedInput, setFocusedInput] = useState(storageProviders.Dropbox);
  return (
    <div className={classes.iconsFormWrapper}>
      <form>
        <label className={`${classes.label} ${focusedInput === storageProviders.Dropbox ? classes.selectedService : ''}`}>
          <DropboxIcon/> <span className={classes.iconName}>Dropbox</span>
            <input type="radio" onChange={() => setFocusedInput(storageProviders.Dropbox)} name="signup-service" value="dropbox" className={classes.input} /> 
        </label>
        <label className={`${classes.label} ${focusedInput === storageProviders.GoogleDrive ? classes.selectedService : ''}`}>
          <GoogleDriveIcon/> <span className={classes.iconName}>Google Drive</span>
          <input type="radio" onChange={() => setFocusedInput(storageProviders.GoogleDrive)} name="signup-service" value="drive" className={classes.input} /> 
        </label>
        <label className={`${classes.label} ${focusedInput === storageProviders.Box ? classes.selectedService : ''}`}>
          <BoxIcon/> <span className={classes.iconName}>Box</span>
          <input type="radio" onChange={() => setFocusedInput(storageProviders.Box)} name="signup-service" value="box" className={classes.input} /> 
        </label>
      </form>
    </div>
  )
}

There's a common pattern there that you could probably move into a reusable component but you get the jist of it. 那里有一个常见的模式,您可能会进入可重用的组件,但是却掌握了它的精髓。

This code will work if react version is more than 16 如果react版本大于16,则此代码将起作用

import React, { useState } from 'react';

const SignupRadioIcons = () => {
    const classes = useStyles();
    const [selectedService, setSelectedService]= useState('dropbox');

        return (
            <div className={classes.iconsFormWrapper}>
                <form>
                    <label className={`${classes.label} ${selectedService === 'dropbox' ? classes.selectedService : undefined}`}>
                         <DropboxIcon/> <span className={classes.iconName}>Dropbox</span>
                          <input type="radio" onChange={(e)=> setSelectedService('dropbox')} name="signup-service" value="dropbox" className={classes.input} /> 
                    </label>
                    <label  className={`${classes.label} ${selectedService === 'googleDrive' ? classes.selectedService : undefined}`}>
                         <GoogleDriveIcon/> <span className={classes.iconName}>Google Drive</span>
                          <input type="radio" onChange={(e)=> setSelectedService('googleDrive')} name="signup-service" value="drive" className={classes.input} /> 
                    </label>
                    <label className={`${classes.label} ${selectedService === 'box' ? classes.selectedService : undefined}`}>
                         <BoxIcon/> <span className={classes.iconName}>Box</span>
                          <input type="radio" onChange={(e)=> setSelectedService('box')} name="signup-service" value="box" className={classes.input} /> 
                    </label>
                </form>
            </div>
        )
}

You can set state to the currently selected radio's value, then use a conditional statement to check if the selected value equals the currently selected state in order to apply css . 您可以将state设置为当前选定的无线电值,然后使用条件语句来检查选定值是否等于当前选定状态,以应用css

I would recommend converting your radio's into JSON objects, then looping through them - this makes things a lot easier. 我建议将您的电台转换为JSON对象,然后遍历它们-这使事情变得容易得多。

I have provided an example of how to handle this without using a loop, as well as with using a loop in the SandBox below. 我提供了一个示例,说明如何在不使用循环的情况下以及在下面的SandBox中使用循环的情况下进行处理。

编辑react-material-ui-change-style-radio-onChange

Example Code Using JSON & Looping: 使用JSON和循环的示例代码:

import React, { useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import Dropbox from "./Dropbox.js";
import Box from "./Box.js";
import Drive from "./Drive.js";

const base = {
  fontSize: "20px"
};

const useStyles = makeStyles(theme => ({
  base: {
    ...base
  },
  selected: {
    ...base,
    fontSize: "40px",
    backgroundColor: "yellow",
    textDecorationLine: "underline"
  }
}));

const radioObjects = [
  {
    label: Dropbox,
    value: "dropbox"
  },
  {
    label: Drive,
    value: "drive"
  },
  {
    label: Box,
    value: "box"
  }
];

export default function WithLoop() {
  const classes = useStyles();
  const [currentlyChecked, setCurrentlyChecked] = useState();

  function handleChange(event) {
    setCurrentlyChecked(event.target.value);
    // do work
  }

  return (
    <div>
      <form>
        {radioObjects.map(RadioItem => {
          return (
            <div key={RadioItem.value}>
              <label
                className={
                  currentlyChecked === RadioItem.value
                    ? classes.selected
                    : classes.base
                }
              >
                <RadioItem.label />
                <input
                  value={RadioItem.value}
                  onChange={handleChange}
                  type="radio"
                  name="signup-service"
                />
              </label>
            </div>
          );
        })}
      </form>
    </div>
  );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM