Как сделать так, чтобы текстовое поле FieldArray в редукционной форме имело только чтение с начальными значениями, но не при нажатии нового поля field.push?

Мне нужно создать редукционную форму, которая загружает данные в модальное окно с начальными значениями. Одно из полей (quoteField) должно отображаться с readOnly, когда есть исходные данные. В данных (initialValue) также будет хотя бы одна цитата, так как это требование. Но нажатие новой цитаты fields.push({})} для добавления в форму должно быть произвольным текстом (не только для чтения)

Я пробовал использовать readOnly={pristine}, readOnly={pristine && initial} и т. д. в компоненте. Это работает, пока я не добавлю другое поле; fields.push({})} ИЛИ если я щелкну внутри другого элемента формы. Это действие делает поле цитаты (с начальным значением) снова доступным для редактирования. Он должен оставаться только для чтения.

Я попробовал разные варианты мета:объектов, но ни один из них не дает нужной мне функциональности. Все работает нормально, кроме этой проблемы

 // removed imports

    class EditReduxForm extends React.Component {

      constructor(props) {
      super(props);

 // removed handlers and state 

      }


 // removed function for submitting

      render() {
        const { valueForPRI } = this.state;
        const {fields:{addingName, quoteField}, array: { push }, handleSubmit, addCustom, onNewRequest, form, input, valid, reset, pristine, submitting } = this.props;


        return (
            <span>
                <form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
                  <Field name="addingName" component={formElement.renderName} value={valueForPRI} >{this.menuItemsPRI(valueForPRI)}</Field>
                  <FieldArray name="quoteField" component={formElement.renderEditQuote} /> // ***** <= this element ******
                {actions} <span className="require"> <span className="ast">*</span> required field</span>
                  <br/>
                </form>
          </span>
        );
      }

    }//end edit class

    EditReduxForm = reduxForm({
      form: 'editForm',
      fields: ['addingName', 'quoteField[]'],
      enableReinitialize: true,
      validate,
    })(EditReduxForm);


    EditReduxForm = connect(
      state => ({
        initialValues: {
          addingName: state.loadFormValues.addingName,
          quoteField : state.loadFormValues.quoteField,
        }
      })
    )(EditReduxForm )

    export default EditReduxForm;

а поля формы подтягиваются из другого файла.

  // removed imports


        export const renderName = ({ field, input, label, type, meta: { touched, error, pristine}, children, ...custom  }) => (
           <ul>
              <li>
                <Field
                    {...input}
                    component           ={SelectField}
                    onChange            ={(event, index, value) => input.onChange(value)}
                    children            ={children}
                    className           ="priorityAutoCompleter"
                    id                  ="addingPriority"
                    errorText           ={touched && error }
                    {...custom}
                />
              </li>
          </ul>
        )


        const renderEditQuote = ({ fields, field, input, value, label, type,  meta: { pure, touched, error, pristine, dirty, initial}, children, ...custom, }) => (
          <ul>
            <li>
              <label htmlFor="quoteField">Quote(s)</label>
                <IconButton
                  tooltipPosition     ="top-right"
                  onTouchTap          ={() => fields.push({})}
                 </IconButton>
            </li>
            {fields.map((quote, index) =>
             <ul className="quoteList" key={index}>
                <IconButton
                  type                ="button"
                  tooltip             ="remove"
                  tooltipPosition     ="top-left"
                  className           ="floatRight marginRight"
                  onTouchTap          ={() => fields.remove(index)}
                </IconButton>
              <li className="quoteListLi">
                <Field
                  {...input}
                  component           ={TextField}
                  id                  ="addingQuote"
                  name                ={`${quote}.addingQuote`}
                  type                ="text"
                  multiLine
                  errorText           ={touched && error }
                  children            ={children}
                  {...custom}
                  readOnly            ={ ????? } // // ***<= this element ***
                />
                <span className="error">{error }</span>
                </li>
                <li>
                <Field
                  {...input}
                  component           ={TextField}
                  name                ={`${quote}.addingLabel`}
                  id                  ="addingLabel"
                  type                ="text"
                  onKeyDown           ={(event) => {if (keycode(event) === 'enter') { event.preventDefault() }} }
                  errorText           ={touched && error}
                  readOnly            ={ ????? } // // ** <= this element **
                />
                <span className="error">{error }</span>
                <Field
                  {...input}
                  component           ={TextField}
                  name                ={`${quote}.addingSource`}
                  id                  ="addingSource"
                  type                ="text"
                  onKeyDown           ={(event) => {if (keycode(event) === 'enter') {event.preventDefault() }} }
                  errorText           ={touched && error }
                  readOnly            ={ ????? } // *** <= this element **
                />
                <span className="error">{error }</span>
              </li>

              </ul>
            )}
          </ul>
        )

person dawg8it    schedule 25.09.2017    source источник
comment
Может убрать здесь много лишнего кода? CSS и т. д.   -  person Mark C.    schedule 25.09.2017
comment
я удалил код для сокращения поста   -  person dawg8it    schedule 25.09.2017
comment
Как вы решили это, пожалуйста?   -  person Tom Rudge    schedule 18.10.2018


Ответы (2)


Для чего-то подобного вы можете попытаться заставить Redux-Form сделать всю работу за вас, но я бы предложил взять на себя эту работу.

Поскольку описанная вами логика не обязательно должна быть связана с общим состоянием приложения, а только с состоянием компонента, я бы рекомендовал пойти по этому пути.

Что я имею в виду: вы можете передать обработчик onChange вашему onTouchTap и отключить или включить редактирование в своем поле и использовать для этого состояние локального компонента, что-то вроде this.setState({canEdit : true}), когда выполняется onTouchTap.

person Mark C.    schedule 25.09.2017

У нас было аналогичное требование, согласно которому ключевое поле (в отличие от других полей) должно быть записано и сохранено (в серверной части) только один раз. Однако его можно редактировать любое количество раз между: «API массива push () и сохранением в бэкэнд». После сохранения в бэкенде он становится readOnly/disabled field. Мы сделали это примерно так:

const TextCell = ({
  input,
  label,
  meta: { touched, error, visited },
  elStyle,
  writeOnce,
  ...custom
}) =>
  <TextField
    style={{ width: "100%" }}
    hintText={label}
    disabled={!visited && writeOnce && !!input.value} // ** This works for us **
    errorText={touched && error}
    {...input}
    {...custom}
  />

Вышеупомянутый компонент будет инициализирован, как показано ниже:

<Field
  name={`${rowData}.${fieldName}`}
  component={TextCell}
  label={title}
  writeOnce={true}
/>
person Sundar Rajan Muthuraj    schedule 26.09.2017