javascriptreactjsreact-adminreact-codemirror

Saving changes from a custom component in React-Admin


How do I save the output of a custom component back into the React Admin model?

I have a form with one custom component, which is a CodeMirror field. The changes to everything else save properly. But my CodeMirror field, while working properly as an editor and configured as I want, doesn't save changes.

I'm brand new to React-Admin, and only have limited experience with React, so I imagine I'm missing something basic.

const handleChange = (field) => (val, evt) => {
  // I reach here with `field` set to the instance of MyEditField, with `val`
  // set to the updated editor value, and `evt` the CodeMirror event

  // But now how do I update the underlying record?

  // The following will update the stored copy, but doesn't mark it as a change 
  // to be saved by the dataProvider.   (And I know it doesn't make sense with Redux.)

  field.props.record.myField = val;
}

class MyEditField extends Component {
  constructor(props) {
    super(props)
    this.value = beautify(props.record[props.source]);

    // CodeMirror setup

    this.options = {/* CodeMirror options */}
  }

  render() {
    return (
      <CodeMirror 
        ref="CodeMirror" 
        value={this.value} 
        onChange={handleChange(this)} 
        options={this.options}
      />
    )
  }  
}

export default addField(MyEditField)

I highlight handleChange here not because I think that's where I think the change belongs, but only to demonstrate that if I need a place to hang the right code, I have one. An onBlur would probably be better. The point there is that I do have a way to run whatever code I need with access to my field and to the CodeMirror instance.

(The curried version of handleChange seems slightly strange but was necessary because some combination of the CodeMirror wrapper I'm using and React-Admin seemed to be losing my this reference, even if I used bind(this). But I enter that function with field correctly set, so this works.)

Everything seems correct with CodeMirror here. I think I just need to know how to make the change reflect properly.

I don't think know if it's relevant, but I'm using the React CodeMirror Wrapper.


Solution

  • This is explained in the documentation

    You need to call the onChange function from redux-form input with your new value. This input is a prop react-admin injects to your component.

    The same is true for reading the value by the way. Don't check the record as it will only ever be the initial record. Use the input.value.

    Something like:

    const MyEditField = ({ input }) => (
        <CodeMirror 
            ref="CodeMirror" 
            value={beautify(input.value)} 
            onChange={val => input.onChange(val)} 
            options={{
                // Options
            }}
        />
    )
    
    export default addField(MyEditField)