javascript - 在特定索引处突出显示 React 中 @material-ui/core TextField 的值
问题描述
我正在研究 React,并使用来自 @material-ui/core 的 TextField 创建了一个表单。用户将输入文本,它将传递到后端的服务器,并且将出现一个新文本。我可以通过更改 TextField 的值轻松做到这一点。我的问题是,当我在 TextField 中显示输出时,我希望突出显示一些字符串,如图所示。 之前 之后
我可以从后端获取索引和标记,但我没有找到突出显示部分 TextField 值的方法。我发现的所有内容都是使用 InputProps 设置整个值的样式。我已经尝试使用这个答案和react-highlight-words package,但我无法使用它们设置值,因为它将返回一个对象,并且显示的值将是 [object object] 而不是部分突出显示的字符串我也试过find-substring-in-text-and-change-style-programmatically 并使用TextField而不是Text,但我只想要一个TextField,而不是每个单词的不同TextField。我在我的代码中添加了基于这个答案所做的事情。
这是我的代码的简化版本
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();`
应用程序.js
import React, { Component } from 'react';
import './App.css';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import HomePage from './HomePage';
import 'bootstrap/dist/css/bootstrap.css';
class App extends Component {
render() {
return (
<div className="App">
<>
<Router>
<Switch>
<Route path='/' exact component={HomePage} />
</Switch>
</Router>
</>
</div>
);
}
}
export default App;
主页.js
import React from 'react'
import { TextField, Button } from "@material-ui/core";
const HomePage = () => {
const [value, setValue] = React.useState();
const [indices, setIndices] = React.useState();
const [substrings, setSubstrings] = React.useState();
const handleChange = (event) => {
setValue(event.target.value)
}
const handleChange2 = (event) => {
// What to set?
}
const handleClear = () => {
setValue("")
}
const handleSubmit = () => {
let axios = require('axios')
let data = {
"text": value
}
axios.post('http://127.0.0.1:8000/predict', data)
.then(response => (setValue(response.data.value),
setIndices(response.data.indices),
setSubstrings(response.data.substrings)
))
}
return (
<form noValidate autoComplete="off">
{/*This is the block that I tried from this link https://stackoverflow.com/questions/57808195/react-native-find-substring-in-text-and-change-style-programmatically*/}
{/*
{['red','black','green'].map(item => (
<TextField
InputProps={{
style: {
background: item,
},
}}
value={item}
onChange={handleChange2}
/>
))}
*/}
<TextField
value={value}
rowsMax={15}
InputProps={{
style: {
fontWeight: 500,
},
}}
variant="outlined"
onChange={handleChange}
/>
<Button onClick={handleClear}>Clear</Button>
<Button onClick={handleSubmit}>Submit</Button>
</form>
);
};
export default HomePage;
有没有办法做到这一点?还是更简单的方法,例如将 HTML 代码传递给值?
更新: 我使用原生 contentEditable native 解决了这个问题
正如 Julien Ripet 所建议的那样。这是更新后的 HomePage.js 代码。
import React from 'react'
import {Button } from "@material-ui/core";
const HomePage = () => {
// This handler will listen to the paste event. It will serves as "paste as plain text" to avoid pasting the style.
const handlePaste = (event) => {
// cancel paste
event.preventDefault();
// get text representation of clipboard
var text = (event.originalEvent || event).clipboardData.getData('text/plain');
// insert text manually
document.execCommand("insertText", false, text);
}
// Set the textbox to empty when the clear button is clicked
const handleClear = () => {
var inputText = document.getElementById("textbox");
inputText.innerHTML = "";
}
// Send the text to the server, pass the returned value with its indices to the highlight function to be highlighted and rendered on the same box
const handleSubmit = () => {
// Get the object of the textbox
var inputText = document.getElementById("textbox");
// use innerHTML instead of innerText if you want a string with the html tags
var onlyText = inputText.innerText.trim().replaceAll("\n\n","\n")
// Send data to the server, the response will be (value, indices). Pass it to the highlight function to be highlighted and rendered to the textbox.
/*
let axios = require('axios')
let data = {
"text": onlyText
}
axios.post('http://127.0.0.1:8000/predict', data)
.then(response => (highlight(response.data.value, response.data.indices)))
*/
// Example
var text = "We are trying this text just to see the output";
var indices = [{"start":1, "end":3},{"start":7, "end":8}];
highlight(text, indices)
}
const highlight = (text, indices) => {
// Get the object of the textbox
var inputText = document.getElementById("textbox");
// Split the string to an array of strings for easier processing
text = text.split(" ");
// enclose to be highlighted words with an HTML span of class highlight
for (var i = 0; i < indices.length; i++) {
text[indices[i].start] = "<span class='highlight'>" + text[indices[i].start]
text[indices[i].end -1] = text[indices[i].end -1] + "</span>"
}
// Join the array of strings into one string
var new_text = text.join(' ')
// Update the content of the textbox object with the highlighted text
inputText.innerHTML = new_text;
}
return (
<form noValidate autoComplete="off">
<p
className="textbox"
variant="outlined"
id="textbox"
onPaste={handlePaste} /** Handle the paset event to avoid pasting the style*/
fontWeight = {500}
contentEditable = {true}
></p>
<Button onClick={handleClear}>Clear</Button>
<Button onClick={handleSubmit}>Submit</Button>
</form>
);
};
export default HomePage;
添加到 App.css
.highlight {
background-color: yellow;
}
.textbox {
border: 1px solid #000000;
}
这里有一些对我有帮助的stackoverflow问题:
get the text content from a contenteditable div through javascript
Javascript trick for "paste as plain text" in execCommand
解决方案
欢迎来到 StackOverflow。
无论如何,我看不到通过反应或任何相关软件包解决您的问题。我可以看到它完成的一种方法是将您的 TextField 替换为<p>
具有属性的本机contenteditable="true"
,并根据需要设置样式,可能看起来尽可能接近原始 TextField。
请告诉我您是否设法通过我的替代解决方案或其他方式做到这一点
推荐阅读
- macos - 使用新泽西州 v110.78 的 sml 标准 ML 在 MACOS High Sierra 版本 10.13.6 编译时出错
- c# - 在组合框中选择时显示项目的特定部分
- fax - 通过 RingCentral API 发送传真
- javascript - Lodash:如何简化
- html - android上的谷歌浏览器缩小页面:打开画布菜单
- c# - 如何在单击一次按钮时应用多个事件
- node.js - 如果权限请求被拒绝,如何传递给意图
- css - 选择了 ng-content 的所有可能的直接子级
- android - 当应用程序在后台时,Workmanager 不工作
- maven - 带有 Maven 工件的类路径的 Jar 文件清单