.NET

Working with forms in Griffin.Yo – A Spa library in TypeScript

I’ve pushed a new release that includes a form reader. With a few lines of code you can get a complete JSON object, including hierarchy from a HTML form.

When building a spa you typically do not want forms to be submitted as a regular http request, as it would defeat the purpose of a spa. As you already work with ajax and JSON, why not use it for form submissions too? It’s now possible in Griffin.Yo.

Start by declaring a simple form:

<form id="MyForm">
    <div>
        <label>First name:</label>
        <input name="FirstName" value="Jonas">
    </div>
    <div>
        <label>Last name:</label>
        <input name="LastName" value="Gauffin">
    </div>
</form>

Reading it is done with the FormReader class:

var form = new FormReader("MyForm");
var dto = form.read();
// .. or in your view model:
var dto = ctx.readForm("MyForm");

The returned result is a json document:

{
    "FirstName": "Jonas",
    "LastName": "Gauffin"
}

Radio buttons

Radio buttons are only appended to the JSON document if they are checked, i.e. all other options are ignored:

<form id="MyForm">
    <label>Mood</label>
    <input type="radio" name="Mood" value="Rocking"> Rocking
    <input type="radio" name="Mood" value="Tired" checked> Tired
    <input type="radio" name="Mood" value="Excited"> Excited
</form>

.. results in ..

{
    "Mood": "Tired"
}

Check boxes

The same applies for check boxes:

<form id="MyForm">
    <label>Moods</label>
    <input type="checkbox" name="Moods" value="Rocking"> Rocking
    <input type="checkbox" name="Moods" value="Tired" checked> Tired
    <input type="checkbox" name="Moods" value="Excited" checked> Excited
</form>

.. results in ..

{
    "Moods": ["Tired", "Excited"]
}

.. which is great since we get an array back.

Collections

Collections are typically difficult to handle in HTML forms, as there is nothing in the HTML specification that states how they should be handled. In this implementation they are represented by the “data-collection” attribute.

If you are working with collections that have a single value you use the special input name “[]” to indicate that. Example follows:

<form id="MyForm">
    <div data-collection="Brands">
        <label>Your favorite brands</label>
        <p>In reality you and new inputs using javascript and a button. Just imagine that it's been done here.</p>
        <input name="[]" value="Headlight" />
        <input name="[]" value="OneTrueError" />
        <input name="[]" value="Griffin.Framework" />
    </div>
</form>

Which results in:

{
    "Brands":["Headlight","OneTrueError","Griffin.Framework"]
}

But if your collection contains complex objects you simply specify the name of the items:

<div data-collection="Addresses">
    <label>Enter your addresses</label>
    <input name="Street" value="Here1" />
    <input name="City" value="Falun" />
    <input name="Street" value="Here2" />
    <input name="City" value="Stockholm" />
</div>

Each new item is automatically created when the same input name is repeated. Thus as long as you have all inputs in the same order it works pretty excellent.

Result:

{
    "Addresses": [{
        "Street": "Here",
        "City": "Falun"
    }, {
        "Street": "Here2",
        "City": "Stockholm"
    }]
}

Complex objects

Same thing goes for complex objects. There is nothing in the HTML spec. With this library you have two options.

The first option is to include a <div data-name="SubObjectName"> to wrap the sub object:

<form id="MyForm">
    <div>
        <label>First name:</label>
        <input name="FirstName" value="Jonas">
    </div>
    <div>
        <label>Last name:</label>
        <input name="LastName" value="Gauffin">
    </div>
    <div data-name="Address">
        <h2>Address</h2>
        <label>Street:</label>
        <input name="Street" value="Awesome street"><br>
        <label>Postal code:</label>
        <input name="PostalCode" value="12345"><br>
        <label>City:</label>
        <input name="City" value="Falun"><br>
    </div>
</form>

.. which would generate the following JSON:

{
    "FirstName": "Jonas",
    "LastName": "Gauffin",
    "Address": {
        "Street": "Awesome street",
        "PostalCode": 12345,
        "City": "Falun"
    }
}

The second options is to use dot notation in the input names:

<div>
    <h2>Address</h2>
    <label>Street:</label>
    <input name="Address2.Street" value="Awesome street"><br>
    <label>Postal code:</label>
    <input name="Address2.PostalCode" value="12345"><br>
    <label>City:</label>
    <input name="Address2.City" value="Falun"><br>
</div>

.. which will give you the same result.

Value handling

All values are parsed. For instance the string values “true” and “false” are converted to a JSON bool. Strings containing numbers are converted to JSON numbers. Everything else is treated as a strings.

Summary

The code is available at github.

Related Articles

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button