问题
I'm using the radio button components available from material-ui.com and have set labelPlacement="start"
. This has placed the label on the left side, but I would also like the labels to be left aligned while leaving the radio buttons on the right.
<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>
回答1:
Here is a simple & straightforward solution to your problem using CSS override on the FormControlLabel
component (which encapsulates both the label and the actual control).
We use Material-UI's makeStyles
helper to define the class we'll use to override the default styling of FormControlLabel
. We specifically want to target the root
key (the full list of available CSS override keys for FormControlLabel
is available here), hence we name our class root
to benefit from destructuring and assignment simplification.
We assign the classes
object returned from the useStyles
hook call to the classes
prop of each FormControlLabel
. The long-form of that assignment would be classes={{ root: classes.root }}
but because we named our class root
(which is the name of the key we're targeting) we can simply write 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
Update: additional content about hooks
Say you have the following code (which will fail):
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>
)
}
}
A solution is to externalize the inner component that uses hooks:
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
and in your component generator:
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>
)
}
}
回答2:
Problem
After looking at the css material-UI adds on passing start
in labelPlacement
prop, it gives property
flex-direction: row-reverse;
so it is expected that the element starts from the end (horizontally).
Solution
The workaround solution of it is, add a property
justifyContent: 'space-between';
to the labelPlacementStart
class.
<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
来源:https://stackoverflow.com/questions/56812652/positioning-material-ui-label-to-the-left-with-left-alignment