简体   繁体   中英

How do I create a tab spacing inside textarea ReactJS + Bootstrap?

My main objective is to indent the space within the text area by a particular amount once I click the Tab button.

I am using React JS and Bootstrap. I have created a bootstrap text area in the render function like so.

 <textarea class="col-12 form-control-lg" id="exampleFormControlTextarea1"placeholder="Write some Lyrics" rows="50" onKeyDown={this.useTab()} value={this.state.lyrics}
     onChange={e => this.setState({ lyrics : e.target.value },()=>{
         this.updateSongs("Body")
       })}
   </textarea>

Outside my render function I am running the useTab() method.

useTab(e) {
    console.log(e.keyCode); //press TAB and get the keyCode
    }

I get the below error on running this code.

Unhandled Rejection (TypeError): Cannot read property 'keyCode' of undefined

I did refer to the below solution but was still unable to fix the error.

ReactJS handle tab character in textarea

Do I have to bind the function in the constructor? I'm not really sure why the event is not being captured and what I seem to be missing here.

Please follow this example:

 class App extends React.Component { constructor() { super(); this.textAreaRef = React.createRef(); this.state = { lyrics: "" }; } onChange = event => { this.setState({ lyrics: event.target.value }); }; // Using arrow function so no need to bind 'this' onKeyDown = event => { // 'event.key' will return the key as a string: 'Tab' // 'event.keyCode' will return the key code as a number: Tab = '9' // You can use either of them if (event.keyCode === 9) { // Prevent the default action to not lose focus when tab event.preventDefault(); // Get the cursor position const { selectionStart, selectionEnd } = event.target; // update the state this.setState( prevState => ({ lyrics: prevState.lyrics.substring(0, selectionStart) + "\t" + // '\t' = tab, size can be change by CSS prevState.lyrics.substring(selectionEnd) }), // update the cursor position after the state is updated () => { this.textAreaRef.current.selectionStart = this.textAreaRef.current.selectionEnd = selectionStart + 1; } ); } }; render() { return ( <div className="App"> <textarea ref={this.textAreaRef} className="col-12 form-control-lg" placeholder="Write some Lyrics" rows="50" value={this.state.lyrics} onChange={this.onChange} onKeyDown={this.onKeyDown} /> </div> ); } } ReactDOM.render( <App />, document.getElementById('root'))
 .App { padding: 0.5rem; } /* control tab size */ textarea { tab-size: 8; }
 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div>

You need to add an event listener for your useTab function:

document.addEventListener('keydown', useTab);

Edit:

Instead of an event listener, you can use the onKeyDown handler in your input

useTab = (event) => {
    event.preventDefault();
    console.log(event.key)
}
render: function(){
     return(
         <div>
           <input onKeyDown={this.useTab} />
        </div>
     );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM