Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to setValue on hidden type inputs #284

Closed
beepsoft opened this issue Sep 1, 2019 · 19 comments
Closed

Unable to setValue on hidden type inputs #284

beepsoft opened this issue Sep 1, 2019 · 19 comments
Labels
question Further information is requested

Comments

@beepsoft
Copy link

beepsoft commented Sep 1, 2019

Hi,

Describe the bug
I use react-hook-form 3.23.0. I am not to be able to use setValue on type="hidden" input fields, while setValue works OK on default input fields.

To Reproduce
I have this simple component using semantic-ui-react.

import React from "react";
import useForm from "react-hook-form";
import {Form,Button,Radio} from "semantic-ui-react";

const MyForm: React.FC = props => {
  const { register, handleSubmit, setValue } = useForm();

  const onSubmit = (formData) => console.log(formData);

  let data = {
    start: true
  };

  return (
    <>
      <Form onSubmit={handleSubmit(onSubmit)}>
         <Form.Field>
          <label>Start?</label>
          <input
            type="hidden"
            name="start"
            defaultValue={data.start.toString()}
            ref={register({required: true})}
          />

          <Radio toggle name="start_toggle" defaultChecked={data.start}
                    onChange={(e, radio) => {
                        setValue("start", radio.checked)
                      }
                    } />
        </Form.Field>
        <Button primary type="submit">
          Submit
        </Button>
      </Form>
    </>
  );
};

export default MyForm;

Expected behavior
I want to use Semantic UI's Radio component visualized as a toggle. I would like to store the value of the toggle in a backing field (name="start"). When I have a type="hidden" as the backing field the value always remains "true" (clicking submit logs the form value and start is always "true" there). However if I remove type="hidden" and have a default text field then everything works fine and the value of "start" matches the state of the toggle.

Is there anything special in the handling of hidden inputs? Or what am I doing wrong?

Thanks!

@bluebill1049
Copy link
Member

Thanks for the detailed issue report. hmmm, that's strange. it should just work. Are you happy to provide a codesandbox, I will take a look this when I am in the office :)

@bluebill1049 bluebill1049 added the question Further information is requested label Sep 1, 2019
@beepsoft
Copy link
Author

beepsoft commented Sep 1, 2019

Sure thing! :-) There you are:

https://codesandbox.io/embed/strange-margulis-p5geb?fontsize=14

So, you will have the same form components twice: once with a hidden and once with a text field as the backing field. Switch the toggle, press submit and see the console for the JSON generated by react-hook-forms.

Thank you very much for your effort!

@bluebill1049
Copy link
Member

thanks for the codesandbox :) really helpful i will look into this issue.

@bluebill1049 bluebill1049 added bug Something isn't working and removed question Further information is requested labels Sep 2, 2019
@bluebill1049
Copy link
Member

looks like is the defaultValue which causing this issue:

https://codesandbox.io/s/infallible-frost-kclhg

@bluebill1049 bluebill1049 added question Further information is requested and removed bug Something isn't working labels Sep 2, 2019
@beepsoft
Copy link
Author

beepsoft commented Sep 2, 2019

Oh, thanks! I was not aware of the watch() function. So, what is the actual rule for using watch()? Should it always be used in defaultValue?

@bluebill1049
Copy link
Member

bluebill1049 commented Sep 2, 2019

https://react-hook-form.com/api#watch

you can watch any registered inputs, if you have defined defaultValues in useForm, then it will just flow through.

eg:

const { regsiter } = useForm({ defaultValue: { test: 'bill' } });

const result = watch('test');

<input name="test" ref={regsiter} />

@bluebill1049
Copy link
Member

but this issue was weird, probably only to do with defaultValue with hidden input in React.

@bluebill1049
Copy link
Member

going to close this issue for now :) feel free to reopen if you have other questions

@thomascraig
Copy link

thomascraig commented Dec 27, 2019

Hey @bluebill1049 I've encountered a similar issue with a child input used for file upload which is hidden, touched does not record the change unless I remove the hidden from input element. Any other gotchas?

Does not work:
<input
type="file"
name='files'
hidden
accept='image/*'
ref={register({ required: true })}
defaultValue={watch("files", FileChanged)}
/>

This works:
<input
type="file"
name='files'
accept='image/*'
ref={register({ required: true })}
defaultValue={watch("files", FileChanged)}
/>

@bluebill1049
Copy link
Member

@thomascraig can you set a full codesandbox? are you using setValue API?

@pedrosimao
Copy link

pedrosimao commented Feb 26, 2020

I am facing the same issue. Hidden fields don't seem to work correctly...
I did manage to get it working by setting CSS display: none instead of using type="hidden"

@grumpyoldman-io
Copy link
Contributor

Just chiming in here, I also have a hidden field where setting the value programmatically doesnt work. If I turn the field in to a normal text field it does. For me the solution was using the output of watch('fieldname', initialValue) on the defaultValue of the hidden field.

How are values on fields actually set? Could it be RHF is using an event that isnt supported on hidden fields?

@bluebill1049
Copy link
Member

you can't update input hidden value:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/hidden

try with display: none;

@mattboldt
Copy link

mattboldt commented Sep 15, 2020

@bluebill1049

you can't update input hidden value:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/hidden

I'm not sure this is correct. I interpret MDN's docs as "the user cannot see or edit hidden inputs" -- not that you can't programmatically change hidden inputs to then submit to the server. For our Rails API, we often use dynamically updated hidden inputs to send flags like _destroy to mark an object for destruction.

I'm currently running into this issue myself with some dynamic, deeply nested forms who's schema is generated by rails and rendered by RHF. When I want to delete an association, I need to set that _destroy flag to true and send it back to the server. Something like this:

const { register } = useForm({ resolver: yupResolver(myDynamicSchema) })
const objectsFromServer = {
  nested_resources: [
    { id: 1, value: 123 }, { id: 2, value: 456 }
  ]
}

const deleteLastObject = () => {
  setValue('nested_resources[1][_destroy]', true)
}

return <div>
  {objectsFromServer.nested_resources.map((obj, idx) => (
    <div>
      {/* unregister and hide visible input for deleted object */}
      {obj._destroy ? (
        <i>Object deleted</i>
      ) : (
        <input
          ref={register}
          name={`nested_resources[${idx}][value]`}
          defaultValue={obj.value} />
      )}

      {/* hidden input must be present to send to server */}
      <input
        type="hidden"
        ref={register}
        name={`nested_resources[${idx}][_destroy]`}
        defaultValue={obj._destroy} />
    </div>
  ))}

  <button onClick={deleteLastObject}>Delete</button>
</div>

I know useFieldArray is meant for this kind of behavior, but I couldn't quite get it to work. I can build a full demo of the issue soon, but I just wanted to mention a use-case for updating registered hidden inputs. At the moment, my issue is that when I mark an object for destruction, its other (required) fields appear to still be registered, and it fails validation. Even though only the hidden _destroy field is present.

@bluebill1049
Copy link
Member

@bluebill1049

you can't update input hidden value:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/hidden

I'm not sure this is correct. I interpret MDN's docs as "the user cannot see or edit hidden inputs" -- not that you can't programmatically change hidden inputs to then submit to the server. For our Rails API, we often use dynamically updated hidden inputs to send flags like _destroy to mark an object for destruction.

I'm currently running into this issue myself with some dynamic, deeply nested forms who's schema is generated by rails and rendered by RHF. When I want to delete an association, I need to set that _destroy flag to true and send it back to the server. Something like this:

const { register } = useForm({ resolver: yupResolver(myDynamicSchema) })
const objectsFromServer = {
  nested_resources: [
    { id: 1, value: 123 }, { id: 2, value: 456 }
  ]
}

const deleteLastObject = () => {
  setValue('nested_resources[1][_destroy]', true)
}

return <div>
  {objectsFromServer.nested_resources.map((obj, idx) => (
    <div>
      {/* unregister and hide visible input for deleted object */}
      {obj._destroy ? (
        <i>Object deleted</i>
      ) : (
        <input
          ref={register}
          name={`nested_resources[${idx}][value]`}
          defaultValue={obj.value} />
      )}

      {/* hidden input must be present to send to server */}
      <input
        type="hidden"
        ref={register}
        name={`nested_resources[${idx}][_destroy]`}
        defaultValue={obj._destroy} />
    </div>
  ))}

  <button onClick={deleteLastObject}>Delete</button>
</div>

I know useFieldArray is meant for this kind of behavior, but I couldn't quite get it to work. I can build a full demo of the issue soon, but I just wanted to mention a use-case for updating registered hidden inputs. At the moment, my issue is that when I mark an object for destruction, its other (required) fields appear to still be registered, and it fails validation. Even though only the hidden _destroy field is present.

I think we can set hidden input value: https://codesandbox.io/s/misty-sea-41ko0?file=/src/App.js

@mattboldt
Copy link

@bluebill1049
Copy link
Member

bluebill1049 commented Sep 15, 2020

@bluebill1049 yes but then it resets on submit: https://codesandbox.io/s/ecstatic-satoshi-420w3?file=/src/App.js

That's a valid issue, would you like to create a bug report on this?

@mattboldt
Copy link

@bluebill1049 Sure thing! Thanks for the quick responses #2917

@marceloloureiro

This comment has been minimized.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

7 participants