Creating dynamic changeset rules

ecto
phoenix
#1

I need to create a system like Google forms. I’m still pretty new to Elixir & Phoenix but I think I’ve come up with a plan of attack. I still need your help to execute it or provide samples.

Problem #1: I need to render dynamic input types based on user selected input types.
Solution: Use a helper to render the actual input form with some type of switch statement based on the type.

Problem #2: How do I allow a user to specify custom input validation? Min / Max, Required, etc…
Solution: Some how store a model in the DB and dynamically apply it as a changeset. Maybe build the changeset using this data and pass it in?

If anyone has any reading material or direction, I’d greatly appreciate it. If my line of thinking is wrong, please point me in the right direct.

Thank you for your time!

#2

There are two mayor limitations with changesets and fully dynamic forms.

Nesting without fixed schemas is not really supported right now and changesets work with atom field names, so you cannot use user-provided names here, but you probably need to map to known atom names for the fields.

#3

That is another funky problem. If there’s no way around it… what are my options here? I could re-implement a lot of the validation tools, but then wrapping errors would be impossible. The atom situation feels like a stopper.

#4

I’ve build myself some code to translate the defined fields to :field_1, :field_2, … with a quite arbitrary limit.

#5

You can try to use the technique showed in this video:

@gregvaughn explains in depth the changeset struct and also shows a example of a Anti-Corruption Layer. Even though I recommend watching all the video, you can navigate directly to the minute 20:37 for the example.

In a nut shell, you can give ecto a map with the field and type and this will be used to validate your params:

types = %{name: string, city: string, start: date, end: date}
changeset = Ecto.Changeset.cast({%{}, types}, params, Map.keys(types))

Hope this helps.

Best regards,

1 Like
#6

Eh, it’s not actually that hard a thing, but I do make use of a lot of jsonb. I’ve built pretty much exactly this at work. I just have the database start with a form, that contains many ordered pages, where each page contains multiple fields, and fields are basically a type->jsonb in postgresql (and a couple other things). min/max/required, information that can appear based on answers shown, page to choose next based on answers on a page, etc… Yes it is basically a giant case in function-head form for so many things for it (from displaying to handling to validation to helpers to etc… etc…). I use Drab for the real-time bits but liveview should work just as well if not a bit more heavyweight (drab’s subcommanders are awesome), but even that is optional as you can just validate on page submission anyway (and the page falls back to still working even without javascript anyway).

But yeah, for the actual fields stuff, changeset’s don’t come up much because of so much jsonb handling in the database for them.

#7

Do you have any examples?

#8

What are you specifically wanting an example to do? :slight_smile: