Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.0k views
in Technique[技术] by (71.8m points)

reactjs - How can I set an static outlined div similar to Material-UI's outlined textfield?

I want wrap some TextFields in a outlined container and I found this answer. This work as i want:

enter image description here

But when I click in an inside textfield all the texfields focused:

enter image description here

This is my code:

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

import OutlinedDiv from "./OutlinedDiv";
import TextField from "@material-ui/core/TextField";
import Grid from "@material-ui/core/Grid";

function App() {
  return (
    <div className="App">
      <OutlinedDiv label="DIV">
        <Grid container justify="center" alignItems="center" spacing={3}>
          <Grid item sm={4} xs={12}>
            <TextField label="Text1" variant="outlined" />
          </Grid>
          <Grid item sm={4} xs={12}>
            <TextField label="Text2" variant="outlined" />
          </Grid>
          <Grid item sm={4} xs={12}>
            <TextField label="Text3" variant="outlined" />
          </Grid>
          <Grid item sm={4} xs={12}>
            <TextField label="Text4" variant="outlined" />
          </Grid>
          <Grid item sm={4} xs={12}>
            <TextField label="Text5" variant="outlined" />
          </Grid>
          <Grid item sm={4} xs={12}>
            <TextField label="Text6" variant="outlined" />
          </Grid>
        </Grid>
      </OutlinedDiv>
    </div>
  );
}

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

How I can achive this style and when click in an inside component only focus the selected component?

A response with another approach and the similar solution for outlined div is welcome.

Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Below is an approach that does not leverage TextField or FormControl and thus can be safely used to wrap other inputs. This copies some styles from OutlinedInput and the InputLabel styles applied when within a FormControl.

import React from "react";
import ReactDOM from "react-dom";
import InputLabel from "@material-ui/core/InputLabel";
import NotchedOutline from "@material-ui/core/OutlinedInput/NotchedOutline";
import { withStyles } from "@material-ui/core/styles";
import clsx from "clsx";

const styles = {
  root: {
    position: "relative",
    marginTop: "8px"
  },
  contentWrapper: {
    position: "relative"
  },
  content: {
    padding: "18.5px 14px"
  },
  inputLabel: {
    position: "absolute",
    left: 0,
    top: 0,
    // slight alteration to spec spacing to match visual spec result
    transform: "translate(0, 24px) scale(1)"
  },
  notchedOutline: {}
};

const LabelledOutline = ({ classes, id, label, children, className }) => {
  const [labelWidth, setLabelWidth] = React.useState(0);
  const labelRef = React.useRef(null);
  React.useEffect(() => {
    const labelNode = ReactDOM.findDOMNode(labelRef.current);
    setLabelWidth(labelNode != null ? labelNode.offsetWidth : 0);
  }, [label]);

  return (
    <div className={clsx(className, classes.root)}>
      <InputLabel
        ref={labelRef}
        htmlFor={id}
        variant="outlined"
        className={classes.inputLabel}
        shrink
      >
        {label}
      </InputLabel>
      <div className={classes.contentWrapper}>
        <div id={id} className={classes.content}>
          {children}
          <NotchedOutline
            className={classes.notchedOutline}
            notched
            labelWidth={labelWidth}
          />
        </div>
      </div>
    </div>
  );
};
export default withStyles(styles)(LabelledOutline);

And below is an example using it both without customization and once with customized colors for the label, outline, and content that changes on hover.

import React from "react";
import ReactDOM from "react-dom";
import { withStyles } from "@material-ui/core/styles";

import LabelledOutline from "./LabelledOutline";

const CustomColorLabelledOutline = withStyles({
  root: {
    "& $notchedOutline": {
      borderColor: "purple"
    },
    "&:hover $notchedOutline": {
      borderColor: "orange"
    },
    "& $inputLabel": {
      color: "green"
    },
    "&:hover $inputLabel": {
      color: "blue"
    },
    "& $content": {
      color: "black"
    },
    "&:hover $content": {
      color: "purple"
    }
  },
  notchedOutline: {},
  inputLabel: {},
  content: {}
})(LabelledOutline);

function App() {
  return (
    <div>
      <LabelledOutline id="myID" label="My Label">
        My Content
      </LabelledOutline>
      <CustomColorLabelledOutline label="My Label">
        My Content with custom label and outline color
      </CustomColorLabelledOutline>
    </div>
  );
}

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

Edit LabelledOutline


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...