【问题标题】:How can I set an static outlined div similar to Material-UI's outlined textfield?如何设置类似于 Material-UI 的轮廓文本字段的静态轮廓 div?
【发布时间】:2019-10-15 20:21:24
【问题描述】:

我想将一些 TextFields 包装在一个有轮廓的容器中,我发现了这个 answer。这项工作如我所愿:

但是当我点击一个内部文本字段时,所有的 texfields 都聚焦:

这是我的代码:

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);

我怎样才能实现这种风格,当点击内部组件时,只关注选定的组件?

欢迎使用另一种方法和类似解决方案的概述 div 的响应。

提前致谢。

【问题讨论】:

  • 你能展示你实现第二张图片的代码吗?
  • @tic 我已经更新了我的问题
  • 为什么要将大量文本字段放在另一个文本字段中?你只想要一个大纲吗?
  • 是的,我想要的是一个轮廓分明的 div,就像它在图片中的样子

标签: reactjs material-ui


【解决方案1】:

以下是一种不利用TextFieldFormControl 的方法,因此可以安全地用于包装其他输入。这复制了OutlinedInputInputLabel 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);

下面是一个使用它的示例,既不使用自定义,也使用自定义颜色,用于标签、轮廓和悬停时更改的内容。

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);

【讨论】:

  • 如何更改轮廓/边框和标签的颜色?
  • @425nesp 我稍微更新了LabelledOutline 代码并添加了一个自定义颜色的示例。
【解决方案2】:

还有强制性的 TS 版本(深受@Ryan Cogswell 版本的启发):

import React, { ReactElement, ReactNode } from "react";
import InputLabel from "@material-ui/core/InputLabel";
import NotchedOutline from "@material-ui/core/OutlinedInput/NotchedOutline";
import { makeStyles, Theme } from "@material-ui/core/styles";
import clsx from "clsx";

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

interface Props {
  id: string;
  label: string;
  children: ReactNode;
  className?: string;
}

export default function Conftainer({ id, label, children, className }: Props): ReactElement {
  const [labelWidth, setLabelWidth] = React.useState(0);
  const labelRef = React.useRef(null);
  React.useEffect(() => {
    if (labelRef && labelRef.current && (labelRef.current as any).offsetWidth) {
      setLabelWidth((labelRef.current as any).offsetWidth);
    }
  }, [label]);
  const classes = useStyles();
  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>
  );
}

(任何删除any的编辑都非常欢迎)

【讨论】:

    猜你喜欢
    • 2019-07-28
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-17
    • 2020-02-11
    • 1970-01-01
    相关资源
    最近更新 更多