0

I'm having some trouble trying to dynamically change a TextInput value based on another input using FormDataConsumer.

I have a ReferenceInput that set an AutocompleteInput with some options like below:

<ReferenceInput id="nome" label="Portaauto" source="Portaauto" name="Portaauto" reference="acl-pegaProtocolosConhecidos" alwaysOn >
    <AutocompleteInput id="protocolo" name="Portaautoinput" source="protocolo" translateChoice={false} optionText="nome" />
</ReferenceInput>

The backend returns this record:

[{"id":"http","nome":"http(80)","porta":"80","protocolo":"tcp"},
{"id":"https","nome":"https(443)","porta":"443","protocolo":"tcp"},
{"id":"ntp","nome":"ntp(123)","porta":"123","protocolo":"udp"},
{"id":"dns","nome":"dns(53)","porta":"53","protocolo":"udp"},
{"id":"custom","nome":"custom(10-100)","porta":"10-100","protocolo":"gre"}]

This input is working as expected but I need to change 2 other inputs using user selection. So, If a user selects "http", one input needs to have "80" and other input needs to have "tcp".

I've tried to change just one input in a simply way but I can't even set a TextInput value dynamically using the code below:

const getPortSugestion = (values) => {
    console.log(values)
    return values
};

<FormDataConsumer id="nome">
                {({ formData, record, ...rest }) =>
                    <TextInput
                        name="city"
                        source={getPortSugestion(formData.Portaauto)}
                        value={getPortSugestion(formData.Portaauto)}
                        {...rest}
                    />
                }
</FormDataConsumer>

Using this code the "source" gets changed (with 'nome'), but the "value" isn't changed...

So, how can I change the TextInput value?

And How can I access other attributes from my record so I can change input values using other fields from my record ('porta' and 'protocolo')?

Can anybody help? Thanks in advance.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

3 Answers3

2

I just tried this and it worked for me... It's not your exact code but the concept is the same, should work for you, if not post back what you tried and i'll modify my example.

<TextInput source="dynamic" />
<AutocompleteInput source="category" choices={[
    { id: 'programming', name: 'Programming' },
    { id: 'lifestyle', name: 'Lifestyle' },
    { id: 'photography', name: 'Photography' },
]} />

<FormDataConsumer>
    {({formData, dispatch, ...rest}) => {
        console.log(formData.category);
        if (formData.category && formData.category === 'programming') {
            return (
                formData.dynamic="bang"
            );
        }
    }}
</FormDataConsumer>

funny, i remember having this issue and not getting it working so i did something different, but thought i would revisit when i saw your question..

Greg Belyea
  • 858
  • 1
  • 5
  • 15
2

Not being able to access the full record user selects is one of my biggest pains with RA. As a result, I made my own CustomAutocomplete that allows me to grab the full record selected and store into state.

If you'd like to recreate this is the only change you'd need to make.

YourCustomAutocomplete.js

handleSuggestionSelected = (event, { suggestion, method }) => {
    const { input, getSelected } = this.props;

    const inputValue = this.getSuggestionValue(suggestion);
    if (input && input.onChange) {
        input.onChange(inputValue);
    }

    if(getSelected) {
        getSelected(suggestion);
    }

    if (method === 'enter') {
        event.preventDefault();
    }
};

Then in your form or form component have a basic function that will store into state:

YourForm.js

    getSelected = selectedItem => {
    this.setState({ selectedItem });
  };


             <AutocompleteInput
                inputValueMatcher={inputValueMatcher}
                shouldRenderSuggestions={(val) => {return val.trim().length > 2}}
                limitChoicesToValue={true}
                optionText="name"
                getSelected={this.getSelected}
            />

Now you can use the redux-form's change function as detailed in RA's docs.

So for me, I have user select a vendor for a bill, I store that vendor's data into state and then have several change calls that set vendor's info automatically for user.

0

Well, I used a solution like this: react-admin - How to set input values based on another

const customOnChange = (event)=>{
    const tokenSessionItem = "oidc.user:" + OidcSettings.authority + ":" + OidcSettings.client_id;
    const token = sessionStorage.getItem(tokenSessionItem);

    if (event.Portaauto) {
        if (event.Portaauto !== formBeforeState_Portaauto) {
            const toFetch = dataProviderURL + `/getProtocols/${event.Portaauto}`;
            fetch(toFetch, { method: 'GET', headers: {'content-type': 'application/json', 'Authorization' : `${token}`}})
            .then(response => response.json())
            .then(data => {
                //console.log(data[0].id)
                event.porta = data[0].porta
                event.protocolo = data[0].protocolo
            });
            formBeforeState_Portaauto = event.Portaauto 
        }
    }
}

Form:

export const AcladvCreate = props => (
    <Create {...props}>
        <SimpleForm onChange={customOnChange}>
              <CustomProtocolSugestion />
        </SimpleForm>
    </Create>

Custom element:

Class CustomProtocolSugestion extends React.Component {
    render() {
        return (
            <div>   
                    <div>
                        <FormDataConsumer>
                        {({ formData, ...rest }) => (
                            formData.protocolo !== "ip" ?
                            <TextInput source="porta" label="Porta" validate={validaPorta} />
                            : null
                        )}
                        </FormDataConsumer>
                    </div>

                    <ReferenceInput id="protocolo" label="Protocolo" source="protocolo" reference="acl-protocolosPermitidos" resource="acl-protocolosPermitidos" style={hiddenSelectStylePre}>
                        <SelectInput translateChoice={false} optionText="id"/>
                    </ReferenceInput>

                    <ReferenceInput id="Portaauto" label="?" source="Portaauto" reference="acl-pegaProtocolosConhecidos" resource="acl-pegaProtocolosConhecidos" allowEmpty style={hiddenSelectStyleCurrSelect} >
                        <SelectInput translateChoice={false} optionText="id" />
                    </ReferenceInput>


            </div>
        );
    }
}