#Converting FormData to regular values when processing Form Input

4 messages · Page 1 of 1 (latest)

chilly spear
#

Hey all. I'm currently prototyping a simple ordering page, for which I'm using Astro with SolidJS. I've followed the steps on the related guide (https://docs.astro.build/en/recipes/build-forms-api/) and have so far been successful in setting up the frontend page and the API. But now I'm stuck at validating the input data, because I cannot figure out how to efficiently get the FormDataEntryValues converted to regular strings and especially integers. String operations (simple regex matching and the like) seem to work with these objects, but arithmetic operations wont work because, well, they're not numbers! ICANT I've tried numerous approaches from regular google and ChatGPT, but every solution I find either wont work or seems unnecessarily hacky. Surely theres a swift and easy way to achieve this??

I'll paste my current code in the next message for reference, and thank every reader in advance for their time!

#

Form.tsx (the frontend module)

import { Suspense, createResource, createSignal } from "solid-js"

const [formData, setFormData] = createSignal<FormData>()
const [response] = createResource(formData, postFormData)
const [waiting, setWaiting] = createSignal(false)

async function postFormData(formData: FormData) {
  setWaiting(true)
  const response = await fetch("/api/mail", {
    method: "POST",
    body: formData,
  });
  const data = await response.json()
  setWaiting(false)
  return data
}

function submitData(e: SubmitEvent) {
  e.preventDefault();
  setFormData(new FormData(e.target as HTMLFormElement))
}

function InputForm() {
  return (
    <form onSubmit={submitData}>
--- snip ---
    </form>
  )
}

mail.ts (the API module)

import type { APIRoute } from "astro";

export const post: APIRoute = async ({ request }) => {
  const data = Object.fromEntries(await request.formData());
  
  const name: String = data.name.toString()
  const email: String = data.email.toString()
  const amount: Number = data.amount.toString()
  const shipping = data.shipping

  if (!name || !email || !amount || !shipping) {
    return new Response(
      JSON.stringify({
        message: "Notwendige Felder fehlen"
      }), {
        status: 400
      }
    )
  }

  const mailRegex = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/
  if (!email.toString().match(mailRegex)) {
    return new Response(
      JSON.stringify({
        message: "Ungültige Emailadresse"
      }), {
        status: 400
      }
    )
  }

  if (amount < 1 || amount > 10) {
    return new Response(
      JSON.stringify({
        message: "Ungültige Ticketanzahl"
      }), {
        status: 400
      }
    )
  }
}

Note: while I'd like to focus on the problem at hand, should you think the code is horrid for some reason, please educate me. I'm still learning JS!

#

Oh and please note in the mail.ts file that I am converting the FormData object to a JSON object (at least i think i do) using the Object.fromEntries part. I was hoping the values would be converted to more normal types and become easier to call and process, but they seem to always remain the FormData thing

chilly spear
#

At the end i'd love to have something like this

const name: String = data.name.toString()
const email: String = data.email.toString()
const amount: Number = data.amount
const shipping: Boolean = data.shipping

so each of the form values converted to a regular type and stored in their own variable. But if it cuts down on code length i'll take the keys in an object too.

I feel like im really close to a solution with approaches like this

let [name, email, amount, shipping] = ""
const data = (await request.formData())
for (const pair of data.entries()) {
  pair[0] = pair[1]
}

but obviously the pair[0] part in line 3 doesnt work - it would have to be read literally instead of as a reference for it to set the value of the formerly defined variables. I just cannot wrap my head around how to get the function to actually work, since i'd have to map two arrays into each other like a matrix or something