Cách làm tương tự textarea trong div

Rik

New Member
#1
Mình sử dụng React để xây dựng một thành phần làm nổi bật văn bản.

Để làm điều này, mình có một phần tử textarea và một div trên cùng một level, sao chép giá trị của textarea vào div.

Textarea nằm bên trong thành phần TextArea và div nằm bên trong thành phần HighlightedDiv.

Mình chỉ phát hiện ra rằng các dòng mới và dấu cách không được xử lý bởi div theo cùng một cách mà chúng nằm trong textarea. Vì vậy, khi mình nhập nhiều dấu cách bên trong textarea, div chỉ hiển thị một dấu cách. Và khi mình nhấn enter bên trong textarea, văn bản trong div vẫn nằm trên cùng một dòng.

Mình nhớ việc thêm điều này vào bản sửa lỗi theo kiểu css của div là:
Mã:
white-space: pre;
Và đúng như vậy, nhưng bây giờ mình cũng muốn văn bản của mình giữ wrap khi nó chạm border của div, giống như khi mình sử dụng css sau:
Mã:
white-space: normal;
word-wrap: break-word;
Vấn đề là mình cần cả white-space: pre, và white-space: normal.

Có ai biết một cách khác để đạt được điều đó?

Code của mình:

(Mình đang sử dụng kiểu thư viện, các thành phần được tạo kiểu, do đó phần tử StyledTextArea và Div bên dưới chỉ là một textarea thuần túy và div, tương ứng.)

HighlightTextArea (parent):
Mã:
import React, { Component } from 'react'
import styled from 'styled-components'

import HighlightDiv from './HighlightDiv'
import TextArea from './TextArea'

const Container = styled.div`
  border: 1px green solid;
  width: 100vh;
  padding: 20px;
`


export default class HighlightTextArea extends Component {
  constructor() {
    super()
    this.state = {
      text: ''
    }
  }
  setHighlightTextAreaState = (newStateObject) => {
    for (let key in newStateObject) {
      this.setState({ [key]: newStateObject[key] })
    }
  }
  render() {
    return (
      <Container>
        <TextArea setHighlightTextAreaState={this.setHighlightTextAreaState}/>
        <HighlightDiv text={this.state.text}/>
      </Container>
    );
  }
}
TextArea (Child):
Mã:
import React, { Component } from 'react'
import styled from 'styled-components'

const StyledTextArea = styled.textarea`
  border: 1px solid blue;
  font-family: 'Inconsolata', monospace;
  font-size: 1rem;
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 20;
  color: blue;
  opacity: 0.5;
`

export default class TextArea extends Component {
  constructor(props) {
    super(props)
  }
  handleChange = (event) => {
    console.log("TextArea.handleChange - event.target.value:")
    console.log("\"" + event.target.value + "\"")
    console.log("TextArea.handleChange - event.target.value.length: " + event.target.value.length)
    this.props.setHighlightTextAreaState({
      text: event.target.value,
    })
  }
  // componentDidMount() {
  //   let textAreaRect = document.getElementById("text-area").getBoundingClientRect()
  //
  // }
  render() {
    return (
      <StyledTextArea id="text-area" onChange={this.handleChange}></StyledTextArea>
    );
  }
}
HighlightDiv (Child):
Mã:
import React, { Component } from 'react'
import styled from 'styled-components'

const Div = styled.div`
  border: 1px solid red;
  font-family: 'Inconsolata', monospace;
  font-size: 1rem;
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  color: red;
  text-align: left;
  white-space: normal;
  word-wrap: break-word;
`


export default class HighlightDiv extends Component {
  constructor(props) {
    super(props)
  }
  renderTextHtml = () => {
    // Loop over all characters in this.props.text
    // Check if character is space or enter
  }
  render() {
    return (
      <Div>
        {this.props.text}
      </Div>
    )
  }
}
 
Top