错误时选择组件材料 ui 中的边框颜色覆盖

时间:2021-07-19 05:10:50

标签: reactjs material-ui

我需要在出错时将边框颜色的选择组件覆盖为橙色。我的应用程序中的轮廓输入边框颜色在全局范围内提供绿色。仅在出错时必须覆盖边框颜色

import { FormControl, makeStyles, Select, withStyles } from '@material-ui/core';
const useStyles = makeStyles((theme) => ({
  select: {
    '&:before': {
      borderColor: 'red',
    },
    '&:after': {
      borderColor: 'red',
    },
  },
}));  
    const CustomSelect = ({
      id,
      value,
      name,
      variant,
      onChange,
      error,
      priceType,
    }) => {
      const classes = useStyles();
      return (
        <FormControl size='small' error width='154px'>
          <Select
            id='price-type'
            value={priceType}
            native
            name='priceType'
            variant='outlined'
            onChange={onChange}
            error={true}
            inputProps={{
              style: {
                width: '154px',
              },
            }}
            className={classes.select}
          >
            <option value={''}></option>
            <option value={'Retail'}>Retail</option>
            <option value={'X-East'}>X-East</option>
          </Select>
        </FormControl>
      );
    };
    export default CustomSelect;

2 个答案:

答案 0 :(得分:0)

一般方法

通常在 MaterialUI 中,当我们想要覆盖有条件应用的 MaterialUI 样式时,我们可以使用 classes 属性:

classes={{ root: <class to apply always>, error: <class to apply in error state>}}

您可以在其 API 页面底部阅读有关 CSS API 以及适用于给定组件的类的信息。

或者,我们可以使用更复杂的方法,并在组件处于错误状态时简单地应用规则:

className={ error ? <class to apply in error state> : undefined }

选择组件

Select 组件的编写时间似乎与大多数其他 MaterialUI 输入组件不同。这是我基于 API 和代码风格的直观印象,但我可能错了。不过,Select 组件根据 Input 属性的值使用 FilledInputOutlinedInputvariant 之一。由于您使用 outlined,因此我将在考虑 OutlinedInput 的情况下继续回答此问题。我还将使用绿色作为边框而不是橙色,因为它与红色的区别更加明显。

天真地,我会通过查看 Select 组件的 CSS API 来解决这个问题,然后再仔细查看 OutlinedInput to which remaining properties of the Select component are spreadSelect 组件上不存在适用的 CSS API 类来实现您的目标,但 OutlinedInput 有一个 error 类,其描述如下:

Pseudo-class applied to the root element if error={true}.

如果我们检查开发工具中的 OutlinedInput,我们可以看到带有边框的元素是位于 fieldsetroot 元素内的 OutlinedInput (注意:不是 rootSelect 元素)。如果我们使用 error 类,我们最终会在 rootOutlinedInput 元素上应用一个额外的类,这不是我们想要的。尽管如此,我们可以应用一个引用上述子元素的类......这会起作用。

还有一个 css 类 notchedOutline,我们可以看到它应用于这个 fieldset 导致边框。这里的困境是,如果我们能够向此类添加一些 css,那么它将所有时间应用在 fieldset 上,但我们想应用它处于错误状态。

这为我们提供了四种通过 CSS API 影响 css 的可能策略:

  • 有条件地(出错时)将 css 添加到以子 root 为目标的基础 OutlinedInputnotchedOutline 类。
  • 将 css 添加到以 root 状态和子 OutlinedInput 为目标的基础 errornotchedOutline 类。
  • 将 css 添加到基础 error 和目标子级 OutlinedInputnotchedOutline 类。
  • 有条件地(出错时)将 css 添加到基础 notchedOutlineOutlinedInput 类。

请注意,第二个和第三个更可取,因为它们不需要我们有条件地添加一个类;这是由 MaterialUI 处理的。

在最好的情况下,我希望 Select 组件将其所有不存在的道具转发给它内部使用的元素,在本例中为 OutlinedInput,但显然,它确实如此不转发它部分支持的元素部分(classes 属性)。这意味着如果我们提供 classes.errorclasses.notchedOutline,MaterialUI 将抱怨

Material-UI: The key `XXXX` provided to the classes prop is not implemented in ForwardRef(Select).

而不是将 prop 转发到底层 OutlinedInput。我不知道这是否是一个错误,但这是目前的工作方式。

这意味着我们不能通过 classes 组件的 Select 属性使用上述四种策略中的任何一种。一种解决方法是使用 Select className 道具,该道具被转发到 OutlinedInput,后者又将其转发到 InputBase,后者将其转发到本机元素,这是相同的作为 rootOutlinedInput 元素。因此,如果我们可以访问底层 OutlinedInput 本身,我们可以使用上述所有策略,否则只能使用前两个(然后通过 classNameSelect 属性)。

解决方案

1。设置整个应用的全局错误颜色

如果您希望整个应用程序的错误颜色不是红色,请提供一个主题来更改用于错误的颜色。这是最好的方法,因为它还会更改辅助文本和标签的颜色,否则这些颜色将与 Select 输入的边框颜色不同。

import green from '@material-ui/core/colors/green';

const theme = createTheme({
    palette: {
        error: {
            main: green[500]
        },
    },
});

这是一种干净且非黑客的方法,也是我推荐的方法。但是,如果您不希望更改错误的一般颜色,这可能不是一个好的解决方案,即使您可以将应用程序的本地部分包装在自己的主题中.

2.覆盖错误状态下用于 notchedOutline 的类

这是一种广泛的解决方法,因为您可以使用上述四种策略以多种不同的方式来解决此问题。所有解决方案的缺点是,它们或多或少有点笨拙,它们只影响 Select 的边框,这意味着当组件处于错误状态时,辅助文本和标签的颜色将与边框不同(您也可以为它们添加样式,使所有这些都非常复杂且难以实现)。

2.a 全局覆盖/默认 OutlinedInput

我们可以为 OutlinedInput 创建一个具有全局覆盖的主题。由于我们随后操纵了 OutlinedInput 本身,因此我们可以使用上述所有四种策略。

全局覆盖/默认 OutlinedInputroot 类定位 {{ 1}} 孩子

只有当组件处于错误状态时,才必须有条件地应用此主题。这很复杂,不是一个好的选择。

全局覆盖/默认 notchedOutline 用于 {{1 }} 类针对 OutlinedInput 状态和 root 子级
error

这个效果很好,并且针对 notchedOutline const themeWithOverrides = createTheme({ overrides: { MuiOutlinedInput: { root: { "&$error": { "& $notchedOutline": { border: "1px solid green" } } } } } }) 类,其 css 仅在它处于 OutlinedInput 状态时才适用并应用于其 root 子级。选择器是指已经在该组件的主题中默认定义的 css 类。

全局覆盖/默认 errornotchedOutline 类和 {{ 1}} 孩子
OutlinedInput

此解决方案导致 MaterialUI 出现错误消息

error

这反过来又建议我们使用以前针对 notchedOutline 类的解决方案。

全局覆盖/默认const themeWithOverrides = createTheme({ overrides: { MuiOutlinedInput: { error: { "& $notchedOutline": { border: "1px solid green" } } } } }) 类的Material-UI: The `MuiOutlinedInput` component increases the CSS specificity of the `error` internal state.
root

这将始终应用我们不想要的样式,因此必须有条件地应用主题,这很麻烦,因此根本不推荐使用此解决方案。

2.b OutlinedInput 组件的 Css 类

理论上,我们也可以在这里使用上述所有四种策略。但是,由于我们没有操作 notchedOutline 本身,并且由于 MaterialUI 不会将未为 const themeWithOverrides = createTheme({ overrides: { MuiOutlinedInput: { notchedOutline: { border: "1px solid green" } } } }) 定义的 Select props 转发到底层组件,因此只剩下两个。< /p>

将 css 类有条件地添加到 OutlinedInputclasses 属性,该属性应用于面向子 Select
className Select 组件
OutlinedInput

此解决方案既使用文字 MaterialUI css 类,也要求我们有条件地添加该类。最后,我们必须使用 root 修饰符来覆盖 MaterialUI 默认行为的特异性。总而言之,这有点像黑客的味道。

将 css 类添加到 notchedOutlineconst useStyles = makeStyles((theme) => ({ errorState: { "& .MuiOutlinedInput-notchedOutline": { border: "1px solid green !important" } } })) ... <Select ... className={ errorFlag ? classes.errorState : undefined } ... </Select> 属性,该属性应用于 !important className 组件,仅在 {{ 1}} 状态
Select

这稍微好一点,因为我们不需要有条件地应用样式。此外,只要在 MaterialUI 默认样式之后注入此样式,我们就可以省略 OutlinedInput 修饰符,因为此规则实现了与 MaterialUI 默认行为相同的特异性。这种方法绝对优于以前的方法。

2.c 底层root组件的Css类通过{{1} } 支持 notchedOutline

error 组件接受一个属性 const useStyles = makeStyles((theme) => ({ errorState: { "&.Mui-error": { "& .MuiOutlinedInput-notchedOutline": { border: "1px solid green" } } } })) ... <Select ... className={ classes.errorState } ... </Select> ,它允许您定义要使用的自己的输入组件。在这里,我们可以使用自定义组件,该组件返回带有您想要的修改的 !important

OutlinedInput

因为我们在这里可以直接针对 input 工作,所以我们可以使用它的 CSS API,从而使用前面描述的所有四种策略。

请注意,要按照本书进行操作,您还应该将传入的 SelectSelect 与您默认分配的类合并。

有条件地将 css 类添加到 input 道具目标孩子 OutlinedInput

由于我们现在可以访问 export default function CustomInput(props) { return ( <OutlinedInput {...props} <CHANGES HERE> /> ) } 属性,因此有条件地提供此类不是一个明智的选择。

将 css 类添加到 OutlinedInput 道具定位状态 {{1} } 和孩子classes.error

同样,由于我们现在可以访问 classes.notchedOutline 属性,因此在此处提供一个针对 classes.root 状态的类而不是直接针对它是一种额外的解决方法,因此不推荐使用。

将 css 类添加到 notchedOutline 道具定位子 classes.error
classes.root

这是一个很好的选择,它允许我们将组件是否处于错误状态的决定留给 MaterialUI。使用字面量 MaterialUI css 类有点麻烦,我们必须提供 error 标志来覆盖 MaterialUI 默认行为的更高特异性。

在错误状态下有条件地将 css 类添加到 notchedOutline 道具
classes.error

这和上一个一样好。它使我们免于使用文字 MaterialUI css 类,但它迫使我们有条件地添加类。同样在这里,我们必须提供 error 标志以覆盖 MaterialUI 默认行为的更高特异性。

结论

这么简单的事情,好像改起来挺复杂的,真可惜。尽管如此,最好的解决方案似乎是:

如果您想为应用中的所有输入提供与标签和帮助文本一致的统一外观的强大解决方案,请使用全局错误颜色覆盖。

classes.error

如果您希望在所有 notchedOutline 中使用统一的错误颜色,并且如果您对不协调的标签和帮助文本没有意见,请对 const useStyles = makeStyles((theme) => ({ error: { "& .MuiOutlinedInput-notchedOutline": { border: "1px solid green !important" } } })) export default function CustomInput(props) { const classes = useStyles() return ( <OutlinedInput {...props} classes={{ ...props.classes, error: classes.error }} /> ) } 使用全局覆盖。

!important

如果您需要对单个或几个 classes.notchedOutline / const useStyles = makeStyles((theme) => ({ errorOutline: { border: "1px solid green !important" } })) export default function CustomInput(props) { const classes = useStyles() return ( <OutlinedInput {...props} classes={{ ...props.classes, notchedOutline: errorFlag ? classes.errorOutline : undefined }} /> ) } 进行一次性更改,请使用自定义输入,该输入在组件处于错误状态时有条件地覆盖 !important如果您可以接受颜色不协调的标签和辅助文本。我更喜欢这个解决方案,因为我不喜欢在我的代码中使用文字 MaterialUI css 类。

import green from '@material-ui/core/colors/green';

const theme = createTheme({
    palette: {
        error: {
            main: green[500]
        },
    },
})

这是一个code sandbox with some of these recommended examples

答案 1 :(得分:0)

您可以使用这种样式

const useStyles = makeStyles((theme) => ({
  select: {
    borderColor:'#f00',
    '&:focus': {
      borderColor: '#f00',
    },
  },
}));