【问题标题】:Positioning material-ui label to the left with left alignment将material-ui标签定位到左侧并左对齐
【发布时间】:2019-11-10 18:02:13
【问题描述】:

我正在使用 material-ui.com 提供的单选按钮组件,并设置了labelPlacement="start"。这已将标签放在左侧,但我还希望标签左对齐,同时将单选按钮留在右侧。

<RadioGroup
    name="switching"
    value="switching"
    onChange={this.handleEstablishingChange.bind(this)}
>
    <FormControlLabel value="switching" control={<Radio />} labelPlacement="start" label={this.props.lang().justswitching} />
    <hr />
    <FormControlLabel value="new_source" control={<Radio />} labelPlacement="start" label={this.props.lang().newsource} />
</RadioGroup>

【问题讨论】:

  • 一些演示问题的代码会很好。
  • 我已编辑问题以包含代码。我希望您会考虑删除任何反对票,因为这是一个严重的明确问题。谢谢!
  • 你是如何设计你的材料组件的?您是否按照 Material-UI 自己的文档的建议使用 JSS?组件 CSS 覆盖?我在您的代码中绝对没有任何样式尝试,只有组件道具的使用。请记住,为了帮助您,其他 SO 用户需要能够重现您的问题,坦率地说,我很惊讶需要提醒具有您经验的人。
  • 我也质疑您的问题已经明确的观点。您说您希望标签左对齐,但您需要单选按钮保持右对齐吗?您希望整个标签+无线电组左对齐、居中还是右对齐?还是您希望标签一直在左边,而单选按钮一直在右边?
  • 我需要标签左对齐,单选按钮右对齐。 IE。标签一直到左边,单选按钮一直到右边。我尝试了很多不同的东西。我不确定包含所有不起作用的东西对我是否有用。我会接受任何可行的解决方案,无论是 JSS、CSS 还是任何其他实现。

标签: material-ui


【解决方案1】:

这是一个简单直接的解决方案,使用FormControlLabel 组件(封装标签和实际控件)上的 CSS 覆盖来解决您的问题。

我们使用 Material-UI 的 makeStyles 帮助器来定义我们将用来覆盖默认样式 FormControlLabel 的类。我们特别希望定位 root 键(FormControlLabel 的可用 CSS 覆盖键的完整列表可用 here),因此我们将我们的类命名为 root 以受益于解构和分配简化。

我们将从useStyles 钩子调用返回的classes 对象分配给每个FormControlLabelclasses 属性。该赋值的长格式是classes={{ root: classes.root }},但因为我们将类命名为root(这是我们要定位的键的名称),所以我们可以简单地写成classes={classes}

import React, { useState } from "react";
import ReactDOM from "react-dom";
import { makeStyles } from "@material-ui/core/styles";
import { RadioGroup, FormControlLabel, Radio } from "@material-ui/core";

const useStyles = makeStyles({
  root: {
    // component default is "inline-flex", using "flex" makes the
    // label + control group use the entire width of the parent element
    display: "flex",
    // component default is "flex-start", using "space-between" pushes
    // both flexed content to the right and left edges of the flexbox
    // Note: the content is aligned to the right by default because
    // the 'labelPlacement="start"' component prop changes the flexbox
    // direction to "row-reverse"
    justifyContent: "space-between",
  },
});

const App = () => {
  const [source, setSource] = useState("switching");
  const classes = useStyles();
  return (
    <div>
      <RadioGroup
        name="source"
        value={source}
        onChange={e => setSource(e.target.value)}
      >
        <FormControlLabel
          value="switching"
          control={<Radio />}
          labelPlacement="start"
          label={"Switching"}
          classes={classes}
        />
        <hr />
        <FormControlLabel
          value="new_source"
          control={<Radio />}
          labelPlacement="start"
          label={"New Service"}
          classes={classes}
        />
      </RadioGroup>
    </div>
  );
};

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

Working codesandbox demo

更新:关于钩子的附加内容

假设您有以下代码(会失败):

import React from "react"
import { RadioGroup, FormControlLabel, Radio } from "@material-ui/core"
import { makeStyles } from "@material-ui/core/styles"

const useStyles = makeStyles({
  root: {
    display: "flex",
    justifyContent: "space-between",
  },
})

class ComponentGenerator extends React.Component {

  // ... stuff here ...

  render() {
    const classes = useStyles() // <-- NO! Not a functional component & not
                                // top-level, hooks cannot be used here
    return (
      <RadioGroup
        name="source"
        value={source}
        onChange={this.handleEstablishingChange.bind(this)}
      >
        <FormControlLabel
          value="switching"
          control={<Radio />}
          labelPlacement="start"
          label={"Switching"}
          classes={classes}
        />
        <hr />
        <FormControlLabel
          value="new_source"
          control={<Radio />}
          labelPlacement="start"
          label={"New Service"}
          classes={classes}
        />
      </RadioGroup>
    )
  }
}

一种解决方案是外部化使用钩子的内部组件:

src/components/UI/MyRadio.js

import { FormControlLabel, Radio } from "@material-ui/core"
import { makeStyles } from "@material-ui/core/styles"

const useStyles = makeStyles({
  root: {
    display: "flex",
    justifyContent: "space-between",
  },
})

const MyRadio = ({ value, label }) => {

  const classes = useStyles() // <-- YES! Functional component & top-level

  return (
    <FormControlLabel
      value={value}
      control={<Radio />}
      labelPlacement="start"
      label={label}
      classes={classes}
    />
  )
}

export default MyRadio

在你的组件生成器中:

src/components/ComponentGenerator.js

import React from "react"
import { RadioGroup } from "@material-ui/core"
import MyRadio from "./UI/MyRadio"

class ComponentGenerator extends React.Component {

  // ... stuff here ...

  render() {
    return (
      <RadioGroup
        name="source"
        value={source}
        onChange={this.handleEstablishingChange.bind(this)}
      >
        <MyRadio
          value="switching"
          label={"Switching"}
        />
        <hr />
        <MyRadio
          value="new_source"
          label={"New Service"}
        />
      </RadioGroup>
    )
  }
}

【讨论】:

  • 非常感谢您的出色回答。我的材质 UI 组件是从组件的渲染方法返回的。当我尝试整合这个答案时,我得到“Uncaught Invariant Violation: Invalid hook call”。我以前没有使用过钩子,并且很难遵循文档,因为它似乎依赖于了解一些我还不够熟悉的特定于 React 的术语和概念。关于如何将其集成到 FormControlLabel 创建的组件渲染方法中的任何提示?
  • @BenMcCann Hooks 有非常严格的规则:它们只能函数顶层调用> 组件(即不是类)。因此,如果您尝试在明显是基于类的组件(非功能性)的渲染函数(不是顶级)内声明一个钩子,您将遇到问题。但是,您可以单独声明您的自定义组件(作为功能组件),将其导入您的类组件,然后在您的渲染方法中(有条件或无条件地)使用它。
  • @BenMcCann 我已经在我的答案中添加了一个部分,其中包含一个关于如何通过将代码分解为更小的模块来应对钩子限制的示例(无论如何总是一个更好的主意!)-希望这会有所帮助
【解决方案2】:

问题

在查看 css 材质后,UI 添加了在 labelPlacement 属性中传递 start,它给出了属性

flex-direction: row-reverse;

所以预计元素从末尾(水平)开始。


解决方案

它的变通解决方案是,添加一个属性

justifyContent: 'space-between';

labelPlacementStart 类。

     <FormControlLabel
        value="new_source"
        control={<Radio />}
        labelPlacement="start"
        label={"World"}
        classes={{
          labelPlacementStart: classes.labelPlacementStart
        }}
      />

    const STYLES = theme => createStyles({
      labelPlacementStart: {
         justifyContent: 'space-between'
      }
    })

Look at this codesandbox

【讨论】:

  • 谢谢西拉杰。这似乎并没有完全实现我的目标。我一直在寻找左侧的标签和右侧的单选按钮,它们之间有很大的空间。让我知道这是否有意义或其他澄清是否有用。
  • 那么,您想要容器最左侧的标签和最右侧的单选按钮吗?是吗?
  • 是的,就是这样
  • 然后简单地覆盖类并添加属性justify-content: space-between
猜你喜欢
  • 2015-10-16
  • 2021-09-12
  • 1970-01-01
  • 2021-05-18
  • 2016-08-31
  • 1970-01-01
  • 2013-09-07
  • 2018-08-01
  • 2015-09-18
相关资源
最近更新 更多