#reactjs #material-ui
#reactjs #material-ui
Вопрос:
Я хотел бы, чтобы мое поле типографики стало доступным для редактирования, поэтому я преобразовываю его во ввод.
Теперь я хотел бы, чтобы этот ввод имел тот же стиль.
Как это сделать?
Я попытался скопировать созданный CSS на вход, но это утомительно и казалось не идеальным.
Вот изолированная среда кода для иллюстрации:https://codesandbox.io/s/flamboyant-stonebraker-le1eq?file=/index.js
Комментарии:
1. Можете ли вы взглянуть на «голый ввод» здесь: material-ui.com/components/text-fields/#customized-inputs чтобы посмотреть, работает ли это.
2. Спасибо ShinaBR2, InputBase немного помогает в том, что он сбрасывает стили ввода по умолчанию. Но это не решает первую часть моего вопроса: как извлечь стиль типографики? Идеальной вещью было бы
<InputBase inputComponent={<Typography variant="h4" />} />
но это не работает.3. Я думаю, вы можете использовать
classes
реквизит дляInputBase
компонента, ссылка здесь . Затем вам нужно жестко закодировать или скопировать css из Typography, не уверен, зачем вам это нужно. Но почему бы вместо этого не использовать другой компонент? Один для типографики, один для ввода.4. Да, я могу скопировать CSS в InputBase или input с помощью classes или className, это утомительно, но работает нормально. Мой вопрос: есть ли лучший способ получить стиль из типографики?
5. Нет, при работе с material-ui в большинстве случаев вам просто нужен высокий уровень, использование чистого css — хороший момент, который показывает, что вы делаете неправильно.
Ответ №1:
Я нашел для вас обходной путь, но имейте в виду, что это не идеально, потому что, если вы измените текущий типографский компонент, вам придется снова находить его классы в Chrome devtools, а также типографика с diaplay: none
необходима для материала для отображения стилей…
import React from "react";
import ReactDOM from "react-dom";
import { Button, InputBase, TextField, Typography } from "@material-ui/core";
function App() {
const [isEditing, setIsEditing] = React.useState(false);
const [value, setValue] = React.useState("Edit me");
const toggleIsEditing = () => setIsEditing((b) => !b);
if (isEditing) {
return (
<div style={{ display: "flex", alignItems: "center" }}>
<input
className="MuiTypography-root MuiTypography-h4 MuiTypography-displayInline"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<Typography style={{ display: "none" }} />
<Button size="small" onClick={toggleIsEditing}>
Done
</Button>
</div>
);
}
return (
<div style={{ display: "flex", alignItems: "center" }}>
<Typography variant="h4" display="inline">
{value}
</Typography>
<Button size="small" onClick={toggleIsEditing}>
Edit
</Button>
</div>
);
}
ReactDOM.render(<App />, document.querySelector("#app"));
Комментарии:
1. Спасибо, Адир, мне нравится этот подход! Он обеспечивает точный стиль, менее утомителен, чем копирование отдельных строк css, и кажется более перспективным в том смысле, что я могу обновить пакет material-ui и надеюсь, что имена классов останутся прежними. Используете ли вы эту технику лично?
2. Чтобы динамически сопоставлять имена классов, вы могли бы использовать
const ref = React.useRef()
в<Typography ref={ref} />
компоненте, а затем установитьclassName
для ввода значение<input className={ref.current?.className} />
. Единственное предостережение заключается в том, что вы должны дождаться второго рендеринга, чтобы отобразить редактируемый компонент. Ссылка не будет иметь значения до окончания первого рендеринга.3. @denski хороший подход!
Ответ №2:
<Typography suppressContentEditableWarning={true} contentEditable={true} className={text} onChange={handleChange}>
Some text
</Typography>
Css (чтобы предотвратить неприятно выглядящую границу при нажатии на типографику):
text: {
outline: `0 solid transparent`,
}
Комментарии:
1. Похоже, что onChange не работает. При изменении у него нет никакого события.
2. В завершение этого ответа и моего предыдущего комментария вы можете использовать onInput , потому что onChange , похоже, не работает.
<Typography suppressContentEditableWarning={true} contentEditable={true} onInput={(e) => console.log(e.target.innerText)} >Text</Typography>
Но даже тогда возникают проблемы с возвратом курсора ввода к началу, если вы используете состояние в качестве фактического текста. Одним из решений было бы сделать это onBlur .