Как подделать фокус на Text-поле Material-ui одним нажатием кнопки? - PullRequest
1 голос
/ 24 февраля 2020

В моем веб-приложении есть метод косвенного заполнения текстового поля, и, поскольку оно состоит из нескольких кликов (для контекста, это календарь) и нескольких полей, я хотел бы показать, какое поле они заполняют, когда они нажмите следующую кнопку.

Я не могу поместить фокус в само текстовое поле . Это отвлечет пользователя от интерфейса, на котором он щелкает.

У меня это работает для ввода, но я не могу заставить это работать для текстовых полей. Вот два набора кода, конкретно, где я ошибаюсь?

TextField (не работает)

import React, { useState, useRef, useEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { Button, TextField } from "@material-ui/core";

const useStyles = makeStyles(theme => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  }
}));

export default function Inputs() {
  const classes = useStyles();
  const [focused, setFocused] = useState(false);
  const focusedRef = useRef();
  const toggleFocusOnElement = () => {
    setFocused(prevFocused => !prevFocused);
  };
  useEffect(() => {
    if (focused) {
      focusedRef.current.classList.add("Mui-focused");
    } else {
      focusedRef.current.classList.remove("Mui-focused");
    }
  }, [focused]);
  return (
    <>
      <Button onClick={toggleFocusOnElement}>
        {focused ? "Remove" : "Fake"} focus
      </Button>
      <form className={classes.root} noValidate autoComplete="off">
        <TextField
          inputRef={focusedRef}
          defaultValue="Hello world"
          inputProps={{ "aria-label": "description" }}
        />
      </form>
    </>
  );
}

Edit Material demo

Вход (рабочий)

import React, { useState, useRef, useEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { Button, Input } from "@material-ui/core";

const useStyles = makeStyles(theme => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  }
}));

export default function Inputs() {
  const classes = useStyles();
  const [focused, setFocused] = useState(false);
  const focusedRef = useRef();
  const toggleFocusOnElement = () => {
    setFocused(prevFocused => !prevFocused);
  };
  useEffect(() => {
    if (focused) {
      focusedRef.current.classList.add("Mui-focused");
    } else {
      focusedRef.current.classList.remove("Mui-focused");
    }
  }, [focused]);
  return (
    <>
      <Button onClick={toggleFocusOnElement}>
        {focused ? "Remove" : "Fake"} focus
      </Button>
      <form className={classes.root} noValidate autoComplete="off">
        <Input
          ref={focusedRef}
          defaultValue="Hello world"
          inputProps={{ "aria-label": "description" }}
        />
      </form>
    </>
  );
}

Edit Material demo

Есть ли способ обойти это ограничение или лучший способ подделать фокус?

Ответы [ 3 ]

1 голос
/ 25 февраля 2020

Класс Mui-focused необходимо применить к <div>, который содержит элемент <input> . Команда inputRef устанавливает ссылку на сам элемент <input>, тогда как ref на Input (напрямую или через TextField InputProps) помещается в содержащий div .

Я бы порекомендовал вам вообще не использовать ссылки или useEffect для этой цели и просто применять имя класса более непосредственно:

        <TextField
          InputProps={{ className: focused ? "Mui-focused" : undefined }}
          defaultValue="Hello world"
        />

Edit Fake TextField focus

0 голосов
/ 25 февраля 2020

InputRef={focusedRef} и InputProps={{'ref':focusedRef}} не совпадают.

import React, { useState, useRef, useEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { Button, TextField, Input } from "@material-ui/core";

const useStyles = makeStyles(theme => ({
  root: {
    "& > *": {
      margin: theme.spacing(1)
    }
  }
}));

export default function Inputs() {
  const classes = useStyles();
  const [focused, setFocused] = useState(false);
  const focusedRef = useRef();
  const toggleFocusOnElement = () => {
    setFocused(prevFocused => !prevFocused);
  };
  useEffect(() => {
    if (focused) {
      focusedRef.current.classList.add("Mui-focused");
    } else {
      focusedRef.current.classList.remove("Mui-focused");
    }
  }, [focused]);
  return (
    <>
      <Button onClick={toggleFocusOnElement}>
        {focused ? "Remove" : "Fake"} focus
      </Button>
      <form className={classes.root} noValidate autoComplete="off">
        <TextField
          InputProps={{ ref: focusedRef }}
          defaultValue="Hello world"
        />
      </form>
    </>
  );
}

Edit Material demo

Я не уверен, почему это так, но я можете подтвердить, что приведенный выше код работает для меня в кодах и в окне.

0 голосов
/ 24 февраля 2020

Я думаю, вам нужно просто вызвать focus() и blur() метод элемента управления HTML. Это автоматически даст / уберет фокус с элемента и даст то, что вы хотите достичь.

const toggleFocusOnElement = () => {
    setFocused(prevFocused => !prevFocused);
    if (focused) {
      focusedRef.current.blur();
    } else {
      focusedRef.current.focus();
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...