···1313// - errors on hidden fields?
1414// - custom types for input.hidden, input.disabled, input.required?
15151616-import formz/field.{type Field}
1717-import formz/input.{type Input, Valid}
1818-import gleam/list
1919-import gleam/option.{type Option, None, Some}
2020-import gleam/result
1616+// import formz/field.{type Field}
1717+// import formz/input.{type Input, Valid}
1818+// import gleam/list
1919+// import gleam/option.{type Option, None, Some}
2020+// import gleam/result
21212222-pub type HasDecoder
2222+// pub type HasDecoder
23232424-pub type NoDecoder
2424+// pub type NoDecoder
25252626-pub opaque type Form(format, output, decoder, has_decoder) {
2727- Form(
2828- fields: List(Input(format)),
2929- parse_with: fn(List(Input(format)), decoder) ->
3030- Result(output, List(Input(format))),
3131- decoder: Option(decoder),
3232- )
3333-}
2626+// pub opaque type Form(format, output, decoder, has_decoder) {
2727+// Form(
2828+// fields: List(Input(format)),
2929+// parse_with: fn(List(Input(format)), decoder) ->
3030+// Result(output, List(Input(format))),
3131+// decoder: Option(decoder),
3232+// )
3333+// }
34343535-pub fn new() -> Form(format, a, a, NoDecoder) {
3636- Form([], fn(_, output) { Ok(output) }, None)
3737-}
3535+// pub fn new() -> Form(format, a, a, NoDecoder) {
3636+// Form([], fn(_, output) { Ok(output) }, None)
3737+// }
38383939-pub fn add(
4040- form: Form(
4141- format,
4242- fn(decoder_step_input) -> decoder_step_output,
4343- form_output,
4444- has_decoder,
4545- ),
4646- definition: Field(format, decoder_step_input),
4747-) -> Form(format, decoder_step_output, form_output, has_decoder) {
4848- let Form(inputs, parse_with, decoder) = form
3939+// pub fn add(
4040+// form: Form(
4141+// format,
4242+// fn(decoder_step_input) -> decoder_step_output,
4343+// form_output,
4444+// has_decoder,
4545+// ),
4646+// definition: Field(format, decoder_step_input),
4747+// ) -> Form(format, decoder_step_output, form_output, has_decoder) {
4848+// let Form(inputs, parse_with, decoder) = form
49495050- // create new form with the new field and update the parse
5151- // function to handle the new details from the type of the
5252- // field
5353- Form(
5454- fields: [definition.input, ..inputs],
5555- parse_with: fn(inputs, decoder: form_output) {
5656- // can do let assert because we know there's at least one field since
5757- // we just added one
5858- let assert [input, ..rest] = inputs
5959- case parse_with(rest, decoder), definition.transform(input.value) {
6060- // the form we've already parsed has no errors and the field
6161- // we just parsed has no errors. so we can move on to the next
6262- Ok(next), Ok(value) -> Ok(next(value))
5050+// // create new form with the new field and update the parse
5151+// // function to handle the new details from the type of the
5252+// // field
5353+// Form(
5454+// fields: [definition.input, ..inputs],
5555+// parse_with: fn(inputs, decoder: form_output) {
5656+// // can do let assert because we know there's at least one field since
5757+// // we just added one
5858+// let assert [input, ..rest] = inputs
5959+// case parse_with(rest, decoder), definition.transform(input.value) {
6060+// // the form we've already parsed has no errors and the field
6161+// // we just parsed has no errors. so we can move on to the next
6262+// Ok(next), Ok(value) -> Ok(next(value))
63636464- // the form already has errors even though this one succeeded.
6565- // so add this to the list and stop anymore parsing
6666- Error(inputs), Ok(_value) -> Error([input, ..inputs])
6464+// // the form already has errors even though this one succeeded.
6565+// // so add this to the list and stop anymore parsing
6666+// Error(inputs), Ok(_value) -> Error([input, ..inputs])
67676868- // form was good so far, but this field errored, so need to
6969- // mark this field as invalid and return all the fields we've got
7070- // so far
7171- Ok(_), Error(error) -> Error([input.set_error(input, error), ..rest])
6868+// // form was good so far, but this field errored, so need to
6969+// // mark this field as invalid and return all the fields we've got
7070+// // so far
7171+// Ok(_), Error(error) -> Error([input.set_error(input, error), ..rest])
72727373- // form already has errors and this field errored, so add this field
7474- // to the list
7575- Error(fields), Error(error) ->
7676- Error([input.set_error(input, error), ..fields])
7777- }
7878- },
7979- decoder:,
8080- )
8181-}
7373+// // form already has errors and this field errored, so add this field
7474+// // to the list
7575+// Error(fields), Error(error) ->
7676+// Error([input.set_error(input, error), ..fields])
7777+// }
7878+// },
7979+// decoder:,
8080+// )
8181+// }
82828383-pub fn data(
8484- form: Form(format, a, b, has_decoder),
8585- field: List(#(String, String)),
8686-) -> Form(format, a, b, has_decoder) {
8787- case form {
8888- Form(fields, parse_with, decoder) -> {
8989- fields
9090- // we always prepend fields, so reverse to get correct order
9191- // TODO I think we're going to make it so order doesn't matter
9292- |> list.reverse
9393- |> do_add_input_data(field, [])
9494- |> Form(parse_with, decoder)
9595- }
9696- // FormWithErrors(..) -> form
9797- }
9898-}
8383+// pub fn data(
8484+// form: Form(format, a, b, has_decoder),
8585+// field: List(#(String, String)),
8686+// ) -> Form(format, a, b, has_decoder) {
8787+// case form {
8888+// Form(fields, parse_with, decoder) -> {
8989+// fields
9090+// // we always prepend fields, so reverse to get correct order
9191+// // TODO I think we're going to make it so order doesn't matter
9292+// |> list.reverse
9393+// |> do_add_input_data(field, [])
9494+// |> Form(parse_with, decoder)
9595+// }
9696+// // FormWithErrors(..) -> form
9797+// }
9898+// }
9999100100-fn do_add_input_data(
101101- fields: List(Input(format)),
102102- data: List(#(String, String)),
103103- acc: List(Input(format)),
104104-) {
105105- case fields, data {
106106- // no more fields, we've return all the fields with data we have accumulated
107107- [], _ -> acc
108108- // no more data! return all the fields we have left plus the ones we accumulated
109109- _, [] -> list.append(fields, acc)
110110- // we have a field and data, and the names match. update field to have data
111111- [Valid(name: field_name, ..) as field, ..fields_rest],
112112- [#(data_name, value), ..data_rest]
113113- if field_name == data_name
114114- ->
115115- do_add_input_data(fields_rest, data_rest, [
116116- input.set_value(field, value),
117117- ..acc
118118- ])
119119- // at this point we still have fields and data left, but the first
120120- // field and first data don't match. so we decide we've got no data
121121- // for the first field and move on to the next. but we need to add
122122- // this field without data to the accumulator
123123- [field, ..fields_rest], _ ->
124124- do_add_input_data(fields_rest, data, [field, ..acc])
125125- }
126126-}
100100+// fn do_add_input_data(
101101+// fields: List(Input(format)),
102102+// data: List(#(String, String)),
103103+// acc: List(Input(format)),
104104+// ) {
105105+// case fields, data {
106106+// // no more fields, we've return all the fields with data we have accumulated
107107+// [], _ -> acc
108108+// // no more data! return all the fields we have left plus the ones we accumulated
109109+// _, [] -> list.append(fields, acc)
110110+// // we have a field and data, and the names match. update field to have data
111111+// [Valid(name: field_name, ..) as field, ..fields_rest],
112112+// [#(data_name, value), ..data_rest]
113113+// if field_name == data_name
114114+// ->
115115+// do_add_input_data(fields_rest, data_rest, [
116116+// input.set_value(field, value),
117117+// ..acc
118118+// ])
119119+// // at this point we still have fields and data left, but the first
120120+// // field and first data don't match. so we decide we've got no data
121121+// // for the first field and move on to the next. but we need to add
122122+// // this field without data to the accumulator
123123+// [field, ..fields_rest], _ ->
124124+// do_add_input_data(fields_rest, data, [field, ..acc])
125125+// }
126126+// }
127127128128-pub fn decodes(
129129- form: Form(format, output, decoder, has_decoder),
130130- decoder: decoder,
131131-) -> Form(format, output, decoder, HasDecoder) {
132132- let Form(fields, parse_with, _) = form
133133- Form(fields, parse_with, Some(decoder))
134134-}
128128+// pub fn decodes(
129129+// form: Form(format, output, decoder, has_decoder),
130130+// decoder: decoder,
131131+// ) -> Form(format, output, decoder, HasDecoder) {
132132+// let Form(fields, parse_with, _) = form
133133+// Form(fields, parse_with, Some(decoder))
134134+// }
135135136136-pub fn parse(
137137- form: Form(format, output, decoder, HasDecoder),
138138-) -> Result(output, Form(format, output, decoder, HasDecoder)) {
139139- // we've tagged that we have a decoder with out has_decoder phantom type
140140- // so we can get away with let assert here
141141- let assert Form(fields, parse_with, Some(decoder)) = form
142142- case parse_with(fields, decoder) {
143143- Ok(output) -> Ok(output)
144144- Error(fields) -> Error(Form(fields, parse_with, Some(decoder)))
145145- }
146146-}
136136+// pub fn parse(
137137+// form: Form(format, output, decoder, HasDecoder),
138138+// ) -> Result(output, Form(format, output, decoder, HasDecoder)) {
139139+// // we've tagged that we have a decoder with out has_decoder phantom type
140140+// // so we can get away with let assert here
141141+// let assert Form(fields, parse_with, Some(decoder)) = form
142142+// case parse_with(fields, decoder) {
143143+// Ok(output) -> Ok(output)
144144+// Error(fields) -> Error(Form(fields, parse_with, Some(decoder)))
145145+// }
146146+// }
147147148148-pub fn try(
149149- form: Form(format, output, decoder, HasDecoder),
150150- apply fun: fn(output, Form(format, output, decoder, HasDecoder)) ->
151151- Result(c, Form(format, output, decoder, HasDecoder)),
152152-) -> Result(c, Form(format, output, decoder, HasDecoder)) {
153153- parse(form) |> result.try(fun(_, form))
154154-}
148148+// pub fn try(
149149+// form: Form(format, output, decoder, HasDecoder),
150150+// apply fun: fn(output, Form(format, output, decoder, HasDecoder)) ->
151151+// Result(c, Form(format, output, decoder, HasDecoder)),
152152+// ) -> Result(c, Form(format, output, decoder, HasDecoder)) {
153153+// parse(form) |> result.try(fun(_, form))
154154+// }
155155156156-pub fn get_inputs(form: Form(format, a, b, has_decoder)) -> List(Input(format)) {
157157- form.fields |> list.reverse
158158-}
156156+// pub fn get_inputs(form: Form(format, a, b, has_decoder)) -> List(Input(format)) {
157157+// form.fields |> list.reverse
158158+// }
159159160160-pub fn update_input(
161161- form: Form(format, output, decoder, has_decoder),
162162- name: String,
163163- fun: fn(Input(format)) -> Input(format),
164164-) -> Form(format, output, decoder, has_decoder) {
165165- form.fields
166166- |> list.map(fn(field) {
167167- case field.name == name {
168168- True -> fun(field)
169169- False -> field
170170- }
171171- })
172172- |> Form(form.parse_with, form.decoder)
173173-}
160160+// pub fn update_input(
161161+// form: Form(format, output, decoder, has_decoder),
162162+// name: String,
163163+// fun: fn(Input(format)) -> Input(format),
164164+// ) -> Form(format, output, decoder, has_decoder) {
165165+// form.fields
166166+// |> list.map(fn(field) {
167167+// case field.name == name {
168168+// True -> fun(field)
169169+// False -> field
170170+// }
171171+// })
172172+// |> Form(form.parse_with, form.decoder)
173173+// }
+32-28
formz/src/formz/formz_use.gleam
···11-import formz/field.{type Field}
22-import formz/input.{type Input}
11+import formz/field.{type Definition, type Field}
32import gleam/dict
43import gleam/list
54import gleam/result
···1312}
14131514pub type FormItem(format) {
1616- Item(input: Input(format))
1515+ Item(input: Field(format))
1716 Set(Fieldset(format), items: List(FormItem(format)))
1817}
1918···2120 Fieldset(prefix: String, label: String)
2221}
23222323+pub fn create_form(thing: thing) -> Form(format, thing) {
2424+ Form([], fn(_) { Ok(thing) }, thing)
2525+}
2626+2427pub fn with(
2525- field: Field(format, input_output),
2828+ field: Field(format),
2929+ definition: Definition(format, input_output),
2630 fun: fn(input_output) -> Form(format, form_output),
2731) -> Form(format, form_output) {
2832 // we pass in our placeholder value, and we're going to throw away the
2933 // decoded result here, we just care about pulling out the fields
3034 // from the form.
3131- let next = fun(field.placeholder)
3535+ let next = fun(definition.placeholder)
3636+3737+ let field = field |> field.set_widget(definition.widget)
32383339 // prepend the new input to the inputs from the form we got in the
3440 // previous step.
3535- let updated_inputs = [Item(field.input), ..next.items]
4141+ let updated_inputs = [Item(field), ..next.items]
36423743 // now create the parse function. parse function accepts most recent
3844 // version of input list, since data can be added to it. the list
···4248 let assert Ok(#(Item(input), next_inputs)) = next_item(inputs)
43494450 // transform the input data using the transform/validate/decode/etc function
4545- let input_output = field.transform(input.value)
5151+ let input_output = definition.transform(input.value)
46524753 // pass our transformed input data to the next function/form. if
4854 // we errored we still do this with our placeholder so we can continue
4955 // processing all the fields in the form. we will return a form
5056 // with an error, so if we're on the error track we'll throw away
5157 // the "output" made with this and just keep the errors.
5252- let next_form = fun(input_output |> result.unwrap(field.placeholder))
5858+ let next_form = fun(input_output |> result.unwrap(definition.placeholder))
5359 let form_output = next_form.parse(next_inputs)
54605561 // ok, check which track we're on
···6672 // so far
6773 Ok(_), Error(error) ->
6874 input
6969- |> input.set_error(error)
7575+ |> field.set_error(error)
7076 |> Item
7177 |> list.prepend(next_inputs, _)
7278 |> Error
···7581 // to the list of errors
7682 Error(fields), Error(error) ->
7783 input
7878- |> input.set_error(error)
8484+ |> field.set_error(error)
7985 |> Item
8086 |> list.prepend(fields, _)
8187 |> Error
···9410095101 let sub_inputs =
96102 sub.items
9797- |> map_items(fn(item) { item |> input.set_name(prefix <> "." <> item.name) })
103103+ |> map_inputs(fn(input) {
104104+ input |> field.set_name(prefix <> "." <> input.name)
105105+ })
9810699107 let updated_inputs = [Set(Fieldset(prefix, name), sub_inputs), ..next.items]
100108···144152 }
145153}
146154147147-fn map_items(
155155+fn map_inputs(
148156 items: List(FormItem(format)),
149149- fun: fn(Input(format)) -> Input(format),
157157+ fun: fn(Field(format)) -> Field(format),
150158) -> List(FormItem(format)) {
151159 list.map(items, fn(item) {
152160 case item {
153161 Item(input) -> Item(fun(input))
154154- Set(s, items) -> Set(s, map_items(items, fun))
162162+ Set(s, items) -> Set(s, map_inputs(items, fun))
155163 }
156164 })
157165}
···173181 input_data: List(#(String, String)),
174182) -> Form(format, output) {
175183 let data = dict.from_list(input_data)
176176- let Form(inputs, parse, placeholder) = form
177177- inputs
178178- |> map_items(fn(input) {
179179- case dict.get(data, input.name) {
180180- Ok(value) -> input.set_value(input, value)
181181- Error(_) -> input
184184+ let Form(items, parse, placeholder) = form
185185+ items
186186+ |> map_inputs(fn(field) {
187187+ case dict.get(data, field.name) {
188188+ Ok(value) -> field.set_value(field, value)
189189+ Error(_) -> field
182190 }
183191 })
184192 |> Form(parse, placeholder)
185185-}
186186-187187-pub fn create_form(thing: thing) -> Form(format, thing) {
188188- Form([], fn(_) { Ok(thing) }, thing)
189193}
190194191195pub fn parse(form: Form(format, output)) -> Result(output, Form(format, output)) {
···235239pub fn get_input(
236240 form: Form(format, output),
237241 name: String,
238238-) -> Result(Input(format), Nil) {
242242+) -> Result(Field(format), Nil) {
239243 form
240244 |> get_inputs
241245 |> list.filter(fn(input) { input.name == name })
···245249pub fn map_input(
246250 form: Form(format, output),
247251 name: String,
248248- fun: fn(Input(format)) -> a,
252252+ fun: fn(Field(format)) -> a,
249253) -> Result(a, Nil) {
250254 form |> get_input(name) |> result.map(fun)
251255}
···253257pub fn update_input(
254258 form: Form(format, output),
255259 name: String,
256256- fun: fn(Input(format)) -> Input(format),
260260+ fun: fn(Field(format)) -> Field(format),
257261) -> Form(format, output) {
258262 form.items
259259- |> map_items(fn(field) {
263263+ |> map_inputs(fn(field) {
260264 case field.name == name {
261265 True -> fun(field)
262266 False -> field
···55pub fn make_form() {
66 let choices = [#("Yes", True), #("Maybe", True), #("No", False)]
7788- use a <- formz.with(field("a", fields.text_field()))
99- use b <- formz.with(field("b", fields.integer_field()))
1010- use c <- formz.with(field("c", fields.number_field()))
1111- use d <- formz.with(field("d", fields.boolean_field()))
1212- use e <- formz.with(field("e", fields.email_field()))
1313- use f <- formz.with(field("g", fields.enum_field(letters())))
1414- use g <- formz.with(field("h", fields.indexed_enum_field(choices)))
1515- use h <- formz.with(field("i", fields.list_field(["Dog", "Cat", "Bird"])))
88+ use a <- formz.with(field("a"), fields.text_field())
99+ use b <- formz.with(field("b"), fields.integer_field())
1010+ use c <- formz.with(field("c"), fields.number_field())
1111+ use d <- formz.with(field("d"), fields.boolean_field())
1212+ use e <- formz.with(field("e"), fields.email_field())
1313+ use f <- formz.with(field("g"), fields.enum_field(letters()))
1414+ use g <- formz.with(field("h"), fields.indexed_enum_field(choices))
1515+ use h <- formz.with(field("i"), fields.list_field(["Dog", "Cat", "Bird"]))
16161717 formz.create_form(#(a, b, c, d, e, f, g, h))
1818}
···11-import formz/field
11+import formz/field.{field}
22import formz/formz_use as formz
33import formz_string/fields
44···1818}
19192020fn address_form() {
2121- use street <- formz.with(field.field("street", fields.text_field()))
2222- use city <- formz.with(field.field("city", fields.text_field()))
2323- use state <- formz.with(field.field("state", fields.list_field(states_list())))
2424- use postal_code <- formz.with(field.field("postal_code", fields.text_field()))
2121+ use street <- formz.with(field("street"), fields.text_field())
2222+ use city <- formz.with(field("city"), fields.text_field())
2323+ use state <- formz.with(field("state"), fields.list_field(states_list()))
2424+ use postal_code <- formz.with(field.field("postal_code"), fields.text_field())
25252626 formz.create_form(Address(street:, city:, state:, postal_code:))
2727}