admin-on-rest: Скрыть ввод формы зависит от другого значения ввода

Я не мог найти способ скрыть ввод зависит от некоторого значения записи. Я пытался получить import { formValueSelector } from 'redux-form' чтобы получить текущее состояние, но я не смог.

export default props => 
    <Edit {...props}>
        <SimpleForm>
            <DisabledInput source="id"/>
            <NumberInput options={opts} source="age" />
            {
            props.record.age > 18 &&
                <TextInput options={opts} source="question"/>
            }
        </SimpleForm>
    </Edit>

4 ответа

Вы можете использовать marmelab / aor-зависимый ввод, это компонент для отображения ввода в зависимости от других значений ввода.

Пример использования:

import React from 'react';
import {
    Create, SimpleForm, TextInput, DisabledInput, NumberInput
} from 'admin-on-rest';
import DependentInput from 'aor-dependent-input';

const checkAge = (age) => {
    return parseInt(age, 10) > 18;
};

const UserCreate = (props) => (
    <Create {...props}>
        <SimpleForm>
            <DisabledInput source="id"/>
            <NumberInput source="age" step="1" />

            <DependentInput dependsOn="age" resolve={checkAge}>
                <TextInput source="question"/>
            </DependentInput>
        </SimpleForm>
    </Create>
);

export default UserCreate;

record не меняется, пока вы не отправите заявку, поэтому ваше решение не работает. Я считаю, что решение заключается в использовании formValueSelector, как объяснено в документации приставки, в пользовательских компонентах ввода.

Что-то вроде:

// in src/ConditionalInput.js
import React from 'react';
import { connect } from 'react-redux';
import { formValueSelector } from 'redux-form'
import { TextInput } from 'admin-on-rest/lib/mui`;

const ConditionalInput = ({ isDisplayed, condition, children, ...rest }) => 
    isDisplayed 
        ? React.cloneElement(children, rest)
        : null;

function mapStateToProps(state, props) {
    return {
        isDisplayed: props.condition(formValueSelector('record-form')),
    }
}

export default connect(mapStateToProps)(ConditionalInput);

// in your EditView
export default props => 
<Edit {...props}>
    <SimpleForm>
        <DisabledInput source="id"/>
        <NumberInput options={opts} source="age" />
        <ConditionalInput condition={selector => selector('age') > 18}>
            <TextInput options={opts} source="question"/>
        </ConditionalInput>
    </SimpleForm>
</Edit>

Ответ Франсуа был очень близок, и, честно говоря, мой не настолько чист, но у меня было несколько проблем с ним:

  • selector требует от государства тоже
  • после прохождения в состоянии у меня были проблемы с Trying to access touched of undefined

После некоторого поиска я обнаружил, что касание является мета-атрибутом, см. https://github.com/marmelab/admin-on-rest/blob/master/docs/Inputs.md. И на странице говорится, что <Field> проходит meta и input приписать своему ребенку. Я попытался исправить ответ Франсуа, но я хотел изменить его ответ.

const ConditionalChildRendering = ({isDisplayed, condition, children, ...rest}) => {
  return isDisplayed
    ? React.cloneElement(children, rest)
    : null;
}

const ConditionalInput = connect((state, props) => {
  return  {
      isDisplayed: props.condition(formValueSelector('record-form'), state),
  }
})(ConditionalChildRendering);

...

let conditionalTextField = ({meta, input, name, ...rest}) => {
    return <ConditionalInput {...rest}>
        <TextInput source={name} meta={meta} input={input} {...rest}  />
    </ConditionalInput>;
};

<Field 
    component={conditionalTextField} 
    name="postcode" 
    condition={(selector,state) => selector(state, 'somefield') === 'somevalue'} />

Благодарю Франсуа за то, что он указал мне правильное направление с формами. К сожалению, с этим решением вам нужно будет обернуть каждое поле в переменную, чтобы иметь возможность передавать в <Field>"s component имущество. (но если кто-то знает более хороший способ, пожалуйста, поделитесь, я новичок, чтобы реагировать)

У меня была похожая проблема, но я не смог отобразить ярлык с помощью этого решения, поэтому я внес небольшие изменения, чтобы отобразить ярлык и сделать его более общим.

import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { formValueSelector } from 'redux-form';
import {TextInput,FieldTitle} from 'admin-on-rest';
import { Field } from 'redux-form';


function mapStateToProps(state, props) {
    return {
        isDisplayed: props.condition(formValueSelector('record-form'),state),
    }
}

const ConditionalInput = ({ isDisplayed,source,label,resource,isRequired,component, ...rest }) => {
    if (isDisplayed) {
        return <Field name={source} 
                      component={component} 
                      label={(addLabel)?<FieldTitle
                            label={label}
                            source={source}
                            resource={resource}
                            isRequired={isRequired}/>:null} {...rest} />
    } else {
        return null;
    }        
}

ConditionalInput.defaultProps = {
    addLabel: true,
    isRequired : false
}

ConditionalInput.propTypes = {
    addField: PropTypes.bool.isRequired,
    elStyle: PropTypes.object,
    input: PropTypes.object,
    label: PropTypes.string,
    resource: PropTypes.string,
    source: PropTypes.string,
    isRequired:PropTypes.bool,
    component:PropTypes.object
};

export const GcConditionalInput = connect(mapStateToProps)(ConditionalInput);


...

//then it can be used like this
<SelectInput source="terminationStatus" optionText="label" optionValue="id" choices={terminationStatus} style={inlineBlockStyle} allowEmpty/>               
<GcConditionalInput source="terminationEnteredDate" component={DateInput} condition={(selector,state) => selector(state, 'terminationStatus') !== null}/>
<GcConditionalInput source="terminationComment" component={TextInput} condition={(selector,state) => selector(state, 'terminationStatus') !== null}/>
Другие вопросы по тегам