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.

3 Answers 3

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..

Sign up to request clarification or add additional context in comments.

1 Comment

Nice solution! But i don't think its enough since I needed to access other fields from the record...
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.

1 Comment

Thanks! I'll try later!
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>
        );
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.