Home > Blockchain >  NextJS - How to prevent a form field from rendering and still pass it in the submit action or event?
NextJS - How to prevent a form field from rendering and still pass it in the submit action or event?

Time:10-14

I am updating an existing card record, which has inputs like cardText, source and ownedBy. ownedBy is an array, it is not editable and I don't want the user to see it. But when I do my Patch I want it to be passed along, in order for the value to be preserved.

A quick fix is to set the style of the input field in the form to "display:none", which is what I am doing in the code presented below. Still, this input field is being rendered, and a user who knows how to inpect source code will see the field. I want to prevent that.

export default function Form() {
    const router = useRouter()
    const cardId = router.query.id
    const submitCard = async event => {
      event.preventDefault()
      const res = cardId ? await fetch(
        '/api/cards/' cardId,
        {
          body: JSON.stringify({
            cardText: event.target.cardText.value,
            category: event.target.category.value,
            cardUsers: event.target.cardUsers.value,
            source: event.target.source.value,
            ownedBy: event.target.ownedBy.value.split(","),
          }),
          headers: {
            'Content-Type': 'application/json'
          },
          method: 'PATCH'
        }
      ) : await fetch(
        '/api/cards/insertCard',
        {
          body: JSON.stringify({
            cardText: event.target.cardText.value,
            category: event.target.category.value,
            cardUsers: event.target.cardUsers.value,
            source: event.target.source.value
          }),
          headers: {
            'Content-Type': 'application/json'
          },
          method: 'POST'
        }
      )
      alert("Card Submitted");

    } 

    const [card, setCard] = useState('');

    const fetchCard = async () => {
      const res = await fetch('/api/cards/' cardId)
      const card = await res.json()
      setCard(card);
    }

    useEffect( () => {
      cardId ? fetchCard() : ''
    }, [cardId])
  
    return (
      <div className={styles.container}>
        <Head>
          <title>CardX - {cardId ? 'Edit' : 'New Card'}</title>
          <meta name="description" content="The place to edit or create cards" />
          <link rel="icon" href="/favicon.ico" />
        </Head>
        <form onSubmit={submitCard}>
        <label className={utilStyles.input_label} htmlFor="cardText">Card Text</label>

        <div className={utilStyles.input}>

          <textarea className={utilStyles.input_field} cols="30" rows="3" id="cardText" name="cardText" type="text" defaultValue={card.cardText} required />
         </div>
         
        <label className={utilStyles.input_label} htmlFor="category">What is the card category?</label>

        <div className={utilStyles.input}>
        <select name="category" id="category-select" value={card.category} >
            <option value="">--Please choose an option--</option>
            <option value="Q">Quebra-Gelo</option>
            <option value="P">Profunda</option>
            <option value="D">Divertida</option>
        </select>
        </div>
         <label className={utilStyles.input_label} htmlFor="cardUsers">To whom is this card designed for?</label>

         <div className={utilStyles.input}>

          <textarea className={utilStyles.input_field} cols="30" rows="3" id="cardUsers" name="cardUsers" type="text" defaultValue={card.cardUsers} />

          </div>
          <label className={utilStyles.input_label} htmlFor="source">Where have you found inspiration to create this card?</label>

          <div className={utilStyles.input}>

           <textarea className={utilStyles.input_field} cols="30" rows="3" id="source" name="source" type="text" defaultValue={card.source} />
          </div>

            <input className={utilStyles.input_field} style={{display:"none"}} id="ownedBy" name="ownedBy" type="text" defaultValue={card.ownedBy} />

          <button className={utilStyles.card_button} type="submit">Submit</button>
          <br />
          <Link href="/">
              <a>Back home!</a>
          </Link>
        </form>
      </div>
    )
  }

This code is part of an open source project, and code can be found at https://github.com/diogocsc/cardx.

A published version can be found at https://cardx.vercel.app

CodePudding user response:

Found a tip at https://stackoverflow.com/a/62681621/1461972 and solved it like this:

export default function Form() {
    const router = useRouter()
    const cardId = router.query.id
    async function submitCard(event, ownedBy) {
    event.preventDefault()
    const res = cardId ? await fetch(
      '/api/cards/'   cardId,
      {
        body: JSON.stringify({
          cardText: event.target.cardText.value,
          category: event.target.category.value,
          cardUsers: event.target.cardUsers.value,
          source: event.target.source.value,
          ownedBy: ownedBy,
        }),
        headers: {
          'Content-Type': 'application/json'
        },
        method: 'PATCH'
      }
    ) : await fetch(
      '/api/cards/insertCard',
      {
        body: JSON.stringify({
          cardText: event.target.cardText.value,
          category: event.target.category.value,
          cardUsers: event.target.cardUsers.value,
          source: event.target.source.value
        }),
        headers: {
          'Content-Type': 'application/json'
        },
        method: 'POST'
      }
    )
    alert("Card Submitted")

  } 

    const [card, setCard] = useState('');

    const fetchCard = async () => {
      const res = await fetch('/api/cards/' cardId)
      const card = await res.json()
      setCard(card);
    }

    useEffect( () => {
      cardId ? fetchCard() : ''
    }, [cardId])
  
    return (
      <div className={styles.container}>
        <Head>
          <title>CardX - {cardId ? 'Edit' : 'New Card'}</title>
          <meta name="description" content="The place to edit or create cards" />
          <link rel="icon" href="/favicon.ico" />
        </Head>
        <form onSubmit={(event) => submitCard(event, card.ownedBy)}>
        <label className={utilStyles.input_label} htmlFor="cardText">Card Text</label>

        <div className={utilStyles.input}>

          <textarea className={utilStyles.input_field} cols="30" rows="3" id="cardText" name="cardText" type="text" defaultValue={card.cardText} required />
         </div>
         
        <label className={utilStyles.input_label} htmlFor="category">What is the card category?</label>

        <div className={utilStyles.input}>
        <select name="category" id="category-select" value={card.category} >
            <option value="">--Please choose an option--</option>
            <option value="Q">Quebra-Gelo</option>
            <option value="P">Profunda</option>
            <option value="D">Divertida</option>
        </select>
        </div>
         <label className={utilStyles.input_label} htmlFor="cardUsers">To whom is this card designed for?</label>

         <div className={utilStyles.input}>

          <textarea className={utilStyles.input_field} cols="30" rows="3" id="cardUsers" name="cardUsers" type="text" defaultValue={card.cardUsers} />

          </div>
          <label className={utilStyles.input_label} htmlFor="source">Where have you found inspiration to create this card?</label>

          <div className={utilStyles.input}>

           <textarea className={utilStyles.input_field} cols="30" rows="3" id="source" name="source" type="text" defaultValue={card.source} />
          </div>

          <button className={utilStyles.card_button} type="submit">Submit</button>
          <br />
          <Link href="/">
              <a>Back home!</a>
          </Link>
        </form>
      </div>
    )
  }
  • Related