Skip to content

Instantly share code, notes, and snippets.

@mikekelly
Last active May 9, 2016 22:30
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mikekelly/5086339 to your computer and use it in GitHub Desktop.
Save mikekelly/5086339 to your computer and use it in GitHub Desktop.
what forms could look like in halo
# Form Properties
title
description
target
method
headers
fields
fielsets ??
# Shared Field Properties
type
validators
title
help
# Field Types
Text
Number
Password
TextArea
Checkbox
Checkboxes
Hidden
Select
Radio
Date
DateTime
List
Object
# Field Validators
required
email
url
match
regexp
{
"_links": { "self": { "href": "/users" } },
"_forms": {
"create-user": {
"title": "Create a new widget",
"description": "Enter your widget info and submit to create a new widget",
"target": "/widgets/{id}",
"method": "PUT",
"headers": {
"Content-Type": "application/json"
},
"fields": {
"name": { "type": "Text", "validators": [ "required" ] },
"email": { "type": "Text", "validators": [ "required", "email" ] },
"age": { "type": "Number" },
"homepage": { "type": "Text", "dataType": "url", "validators": [ "url" ] },
"password": { "type": "Password" },
"likes": { "type": "Checkboxes", "options": [ "Computers", "Combat", "Cats" ] },
"ninja": { "type": "Hidden", "value": "This is a hidden field" },
"size": { "type": "Select", "options": [ "large", "small" ] },
"has_answer": { "type": "Radio", "options": [ "yes", "no", "wtf" ] },
"dob": { "type": "Date" },
"favourite_datetime": { "type": "DateTime" },
"things_to_do_before_death": { "type": "List" }
}
}
}
}
@fosdev
Copy link

fosdev commented Mar 5, 2013

Looks good. Couple of initial thoughts:

  • Maybe also support type names defined in http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.1 for m2m uses that just want to define json schemas vs. pass the form to the UI. There may be a few other concepts/properties in the JSON schema to bring over as optional field properties.
  • allow validators to be an array of optional objects, again allowing a little more flexibility for client- (but not necessarily browser-) side validation if the client understands the validator objects.

Does not seem that halo+json extends hal+json in that you don't reference _embedded. Or is that a misunderstanding because you are just highlighting the form related functionality?

Ideally, a halo+json would include _links, _embedded, and _forms convention.

I think that this should support caching forms and there are questions about forms in embedded resources and keeping things DRY and what this all looks like, e.g.

{
  "_links": { "self": { "href": "/users" } },
  "_forms" : { "create-update-user": {...},
  "_embedded" : {
    "user": [
       {
         "_links": { "self": { "href": "/users/1" } },
         "_forms" : { "create-update-user": {...} },
       },
       {"some": "users"},
       {
         "_links": { "self": { "href": "/users/10" } },
         "_forms" : { "create-update-user": {...} },
       }
     ]
   }
}

Clearly this is not optimal from a DRY/performance standpoint. This may be resolved by supporting links attributes in a form definition as well like:

{
  "_links": { "self": { "href": "/users" } },
  "_forms" : { 
      "create-update-user": { "href": "/forms/create-update-users" } 
  }
}

This would not completely DRY the previous example, but it would prevent passing as much redundant data.

Like the direction you are heading.

@mikekelly
Copy link
Author

@fosdev thanks for the feedback, sorry for the super slow reply

not sure about the schema stuff, might leave that for now but it is a fair suggestion so may revisit further down the line.

what sort of stuff did you have in mind for validators-as-objects? you're concerned that strings might be too simple and objects would give more flexibility over time? hmm.. another thing to think about ! :)

halo will be built on top of hal so it will get all of the _links and _embedded jazz

for collection resources where you want to represent an edit form for embedded resources, you could attach the form to the collection resource instead of each of the items, and call it something like "edit-widget". Another approach would be to borrow the "edit" link relation from AtomPub and add one to each of the items. On reflection, I think I actually prefer the edit relation approach.

I plan to move forwards with this so please keep your input coming, it's super helpful to have other people's input.

@xaethos
Copy link

xaethos commented Mar 27, 2013

Adding my thoughts and questions:

  • It has been raised before, but why target instead of href? I seems more consistent to me to use the later. Or is it the not overload the term?

  • Field type names: please make them all lowercase. this is for machine consumption, after all.

  • "Checkboxes" doesn't really make sense to me as a type. A checkbox should be of type "boolean" and take true or false as value. If you want several checkboxes (or switches, or toggles) just put a field for each. There should be other mechanisms for grouping (see below). Just to drive the point through:

    "full_name": { "type": "Texts", "parts": [ "First Name", "Last Name" ] }

    looks plain wrong.

  • "Select" and "Radio" are basically the same thing. They make sense in HTML because they represent specific widgets, but should halo+json concern itself with those UI aspects? A group of radio buttons that look good on a desktop browser will often be grouped into a drop-down in a mobile app. I vote for something like:

    "likes": { `"type": "select", "options": [ ... ], "multiple": true }

    which allows for drop-downs, radio buttons, combo boxes or what have you. multiple can default to false and is there to allow choosing more than one option at a time.

    • P.S.: that is one way of handling "Checkboxes", though not what I had in mind.

    • options as an array of strings is a bit limited... maybe objects that allow for values and labels?

      "options": [
        { "value": "", "title": "No selection" },
        { "value": "dog", "title": "I value loyalty" },
        { "value": "cat", "title": "I'm a megalomaniac" },
      ]
  • Form within forms! Yeah! A form should have a way to link to / embed another form.

    • This would allow for semantic grouping of controls (like your Checkboxes).
    • This also allows clients a bit more control over the presentation. e.g. a desktop app might present all sub-forms in sections on the same screen, while a mobile app might choose to link to each sub-form in a different view.
    • It plays well with the concept of the recursive embedding, which is one of my favorite aspects of hal+json.
    • With a sub-form as a link, this allows you to not embed the form directly. I've worked in an app where a drop-down ended up having literally thousands of options. No having that array embedded with that rest of the form makes a lot of sense.

I'm really exited to see how this ends up!

@asmith-mdsol
Copy link

Thanks for pointing me towards this @fosdev. Liking the look of it! Some thoughts, mainly on the previous comments...

The reason you might want validators as objects is they may need to be parameterized, e.g. you may want to limit a number to a range. Probably worth cribbing off the HTML5 form validation stuff for this.

Like the edit link relation idea.

Agree with @xaethos on staying clear of presentational types like checkbox and towards the underlying semantic types like boolean.

You might want to make the list of options able to be a link, which would be another way of dealing with very long option lists; I've seen lists in the thousands too. This would also allow caching of the options separately from the form (and with different conditions).

Not entirely sold on recursive form embedding at this point.

Anyway, like I said, looking cool, thanks!

@jmonteiro
Copy link

I understand that maybe @mikekelly wants to transparently load this JSON from a client-side JavaScript client and represent elements on screen, so that's why he set Checkbox at the form representation. I like that, but I agree that Checkbox does not reflects the object on the api.

Maybe we can have a separated option for "interface suggestions"?

"likes": {
  "type": "array<string>",
  "options": [ "cats", "dogs", "apples", "oranges" ],
  "multiple": true,
  "interface": "input[type=checkbox]"
},
"countries": {
  "type": "array<string>",
  "options": [ "United States of America", "Brazil", "Italy" ],
  "multiple": true,
  "interface": "select"
},
"under_age_13": {
  "type": "boolean",
  "default": true,
  "interface": "select"
}

This can be entirely optional and simply ignored on backend integration (let's say an API to API integration), but is really relevant when you want to dynamically load a resource and represent it on screen.

Not sure if "interface" is the best name -- maybe "suggested_representation"?

@fosdev
Copy link

fosdev commented May 17, 2013

@mikekelly Presume you are aware of this: http://tools.ietf.org/html/rfc6861. I think it would be useful to consider accommodating this so that one could actually externally define the form and thus look it up as you are working on controls for HALO. Given there is a spec and per my earlier comment on keeping things DRY, this would be a nice option to be able to use as well as whatever the full convention ends up being.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment