Oh, very clever! Looks like it'll do nicely. Thanks!

By on 5/7/2015 7:01 AM ()

The trick is to build the formlet recursively and give it a structure that mirrors the structure of a list:

1
2
3
4
5
6
7
8
9
10
module Formlet =

    let rec List (itemForms: list<Formlet<'a>>) : Formlet<list<'a>> =
        match itemForms with
        | [] ->
            Formlet.Yield []
        | itemForm :: rest ->
            Formlet.Yield (fun x xs -> x :: xs)
            <*> itemForm
            <*> List rest

And here is an example use of this function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let questions =
    [
        "What's your first name?"
        "What's your last name?"
        "How old are you?"
    ]
// Build a formlet per question
questions
|> List.map (fun question ->
    Controls.Input ""
    |> Enhance.WithTextLabel question
    |> Enhance.WithLabelAbove)
// Combine the formlets using the function from above
|> Formlet.List
// Add submit button, form container, action on submit
|> Enhance.WithSubmitButton
|> Enhance.WithFormContainer
|> Formlet.Run (fun responses ->
    List.iter2 (fun q r -> JS.Alert(q + "\n" + r)) questions responses)

Rendered formlet

Also, here is a slightly more complicated but more optimized (tail-recursive) version of Formlet.List:

1
2
3
4
5
6
7
8
9
10
11
12
13
module Formlet =

    let List (itemForms: list<Formlet<'a>>) : Formlet<list<'a>> =
        let rec list (acc: Formlet<list<'a>>) (itemForms: list<Formlet<'a>>) =
            match itemForms with
            | [] -> acc
            | itemForm :: rest ->
                list
                    (Formlet.Yield (fun x xs -> x :: xs)
                     <*> itemForm
                     <*> acc)
                    rest
        list (Formlet.Yield []) (List.rev itemForms)
By on 5/3/2015 2:51 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper