Search code examples
djangoreactjscodemirrorreact-codemirror

React Component using codemirror not sending all data on form submission


I am using django, react and react-codemirror2 in my project where a user can input SQL code. I am running into an issue where only part of the text from textarea exists in request.POST. I am finding that mostly just part of the last line of the textarea is sent. I am baffled.

React component

import React from 'react'
import {UnControlled as CodeMirror} from 'react-codemirror2'
import DjangoCSRFToken from 'django-react-csrftoken'

class SQLForm extends React.Component{
    componentDidMount() {
        let textarea = document.getElementsByTagName('textarea')[0]
        textarea.setAttribute('name', 'sql');
    }

    render(){
        return(
            <div>
                <form action="" method="POST">
                    <DjangoCSRFToken/>
                    <CodeMirror
                      options={{
                        mode: 'text/x-mssql',
                        theme: 'material',
                        lineNumbers: true
                      }}
                      onChange={(editor, data, value) => {
                      }}
                    />
                    <br/>
                    <button type="submit">Submit</button>
                </form>
            </div>
        )
    }
}

export default SQLForm

super simple django view (just to see what is submitted)

def index(request):
    if 'sql' in request.POST:
        print(request.POST['sql'])
        return render(request, 'react.html', {})
    else:
        return render(request, 'react.html', {})

for example, in the text area, if type in the following

SELECT *
FROM whatever
WHERE something=2

print(request.POST['sql']) shows the following at the console

=2

And for completeness, this is the textarea tag when the page loads

<textarea autocorrect="off" autocapitalize="off" spellcheck="false" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" tabindex="0" name="sql"></textarea>

Solution

  • got this to work by not worrying about CodeMirror being in the form. Instead I used state to capture the last value from the CodeMirror onChange function and then assigned that to the value attribute of the button. Switched the name attribute being in the textarea to being in the button itself.

    import React from 'react'
    import {UnControlled as CodeMirror} from 'react-codemirror2'
    import DjangoCSRFToken from 'django-react-csrftoken'
    
    class SQLForm extends React.Component{
        constructor(props){
            super(props)
            this.updateText = this.updateText.bind(this);
            this.state = {
                sql_text: ''
            }
        }
    
        updateText(value){
            this.setState((prevState)=>({sql_text:value}))
        }
    
        render(){
            return(
                <div>
                    <CodeMirror
                          options={{
                            mode: 'text/x-mssql',
                            theme: 'material',
                            lineNumbers: true
                          }}
                          onChange={(editor, data, value) => {
                              {this.updateText(value)}
                          }}
                     />
                    <form action="" method="POST">
                        <DjangoCSRFToken/>
                        <button type="submit" value={this.state.sql_text} name="sql">Submit</button>
                    </form>
                </div>
            )
        }
    }
    
    export default SQLForm