Adding typeahead to textfield

Hi.

Unsure if this is the right category so apologize if so.

I’m becoming more acquainted with redwood, especially the graphql-integration is nice and easy to work with for querying additional data. I have scaffolded Unit and one field is location. In the old PHP-based this is a pulldown menu with handcoded values. I then scaffolded Location so I can store them in the database.

EditUnitCell.js:

export const QUERY = gql`
  query FIND_UNIT_BY_ID($id: Int!) {
    unit unit(id: $id) {
      id
...
      updated_at
    }
    locations {
      id
      location
    }
  }
`
export const Success = ({ unit, locations }) => {
  const [updateUnit, { loading, error }] = useMutation(UPDATE_UNIT_MUTATION, {
    onCompleted: () => {
      navigate(routes.units())
    },
  })
...
}

Locations only contains a handful entries. Ideally I could have normalized the tables, added a foreign key / delete-constraint from the Unit-table to the location-table but but this is just a small application. So I’m gonna store the location as text in the Unit-table.

I looked at a few typeahead-addons for react and tried react-bootstrap-typeahead. This requires bootstrap and redwood already use tailwindcss.

I also looked at How to create an autocomplete input with plain Javascript - DEV Community where they get data using ajax. But is plain javascript the proper way forward or should it be based on react?

Regards
Claus

Hi @kometen! First off,

Unsure if this is the right category so apologize if so.

^^ never worry about this, k? We barely have rules for this kind of thing. Mostly just suggestions :laughing:

I looked at a few typeahead-addons for react and tried react-bootstrap-typeahead. This requires bootstrap and redwood already use tailwindcss.

^^ Well, just the generated Scaffolding CRUD is using tailwindcss in a very lightweight manner. You might decide to swap it out for bootstrap if it gets you what you need. 100% possible.

is plain javascript the proper way forward…

You can definitely use “plain javascript”! React is how you build the UI and each component has it’s respective elements. So you’ll use JS as normal with those elements. I didn’t read through the article in detail, but at a glance the adjustments you’ll need to handle are using the GraphQL API for the ajaxy stuff.

My 2¢ Idea:
What if you scaffold the CRUD for Location separately and pre-add the items you need? Then for Unit CRUD, instead of an autocomplete/add-new for location, you could have a dropdown with the <select> list populated by a query of all locations? You might have already rejected this idea given your use-case (e.g. location list very dynamic or large quantity). But Fwiw in case it helps or generates more ideas.

Thank you for your reply. :slight_smile: This community is so nice and welcoming. Appreciate this a lot.

Yes, you are right, a <select> is the probably the easiest to do. I looked at <Form> in the docs and this suggest the Formik form-builder. Can <Form> and Formik be mixed together?

Regards
Claus

2 Likes

Can <Form> and Formik be mixed together?

^^ hmm, maybe. But in this case, I don’t think you’ll need to go that path. Under the hood of Redwood Form is React Hook Form, which means you can extend Redwood Forms as needed with RHF elements.

More to the point, it looks like our docs are missing the <SelectField>, which is what you’ll want to use! (Sorry about the confusion – I’m creating an Issue to update the docs and check if anything else is missing.) Here’s a link to the Redwood Form code for SelectField: redwood/packages/web/src/form/form.js at 6d72106dce73e8686985f5936db45c885678c235 · redwoodjs/redwood · GitHub

And if you have other questions about React Hook Form implementation, be sure to check out their docs and examples. I find the Form Builder particularly helpful: Form Builder

2 Likes

Thank you so much. Yes, it works. I changed <select> to <SelectField> and it saves the changes.

I assumed select would make it into <Form> when you guys had the time.

Not only did you come with a good solution based on what I wrote. But you are also able to deduce what I’m trying to convey. :slight_smile:

2 Likes

Great to hear and glad you asked!

Most of all, keep on having fun with Redwood :star_struck:

1 Like

Yes, absolutely. :smile:

Heard a podcast called corecursive where Adam interviews Bruce. “So I find that learning a new language mixes a lot of joy in that pain, and that’s when I grow most rapidly as a developer.”

Even though javascript is not a new language react is very new to me. Doing mostly backend-stuff with java (spring boot and postgresql) redwoodjs takes care of all the frontend I strugle with.

I had some problems passing locations to the form when creating units. I pass locations fine when editing a unit. The difference is editing a unit is using a cell where as creating does not.

So after I turned it upside down I realised I could use a cell and utilize the Success component and pass locations to the form.

1 Like

Ditto about React, believe it or not. Lot of us in on the learning curve together. And may we experience just enough pain to motivate but not enough to overwhelm :muscle:

Nice work conceptually understanding how to use Cells! It won’t always be the correct tool, but when you think “data + query” see if a Cell will do the job.

1 Like

I added the locations to an array in a for-loop at the top.

for (let index = 0; index < props.locations.length; index++) {
  location_array.push(props.locations[index].location)
}

Then in the form:

<SelectField
  name="location"
  defaultValue={props.unit?.location}
  errorClassName={CSS.inputError}
  validation={{ required: true }}
>
  {location_array.map((x, y) => (
    <option key={x}>{x}</option>
  ))}
</SelectField>

So when a new location is added it shows up in the select. Thanks again for the kind help. :slight_smile:

2 Likes