HAL-FORMS
A backward-compatible extension for HAL to provide support dynamic runtime input forms. This specification is used in the RESTful Web Clients book.
backward-compatible extension for HAL to support dynamic forms at runtime.
License: MIT License
A backward-compatible extension for HAL to provide support dynamic runtime input forms. This specification is used in the RESTful Web Clients book.
Include a new optional property "multi" for those fields that allow multiple selection (usually Suggests)
Example:
{
"name": "options",
"value": "[]",
"multi": true,
"suggest": [
{"value":"DAY_TRANSFER", "prompt":"day transfer"},
{"value":"RECOVERABLE", "prompt":"recoverable"},
{"value":"NOTIFIABLE","prompt":"notifiable"}
]
}
Hello, I have questions about this project:
I found https://rwcbook.github.io/hal-forms/ which links to https://github.com/RWCBook/hal-forms.
And I see that this is the root github repository https://github.com/mamund/hal-forms/.
Who is the owner and founder? Why is that website not linking to this repository. Is it a fork with changes?
And even more interesting, who are the project founder? Are they involved in the IETF? Is there any chance that this specification becomes recognized by the IETF and maybe become a standard or at least a draft. Maybe it inspires HAL so that it goes directly into HAL.
Otherwise this is a nice project but unfortionately also a proprietrary data format.
I have a usecase where a user has to choose a node in a tree structure.
I could represent that choice as a select/radio input but it could grow too big and it would be nicer if the real tree structure was shown in the form (instead of an flattened structure).
I would prefer to keep select/radio as input type over a new/custom one (tree) because select/radio are standard and degrade gracefully if the client would not know about the new (non-standard) type.
Therefore, I need some extra information about how my input could be rendered.
Is there anything in the current spec that would allow me to do that?
I had something like this in mind:
{
"_templates" : {
"default" : {
...
"properties" : [
{
"name" : "directory",
"prompt" : "Directory",
"type" : "select",
"options" : {
"inline" : [
"foo",
"foo/bar",
"foo/bar/baz",
"foo/bar/qux",
"bar",
"bar/baz/qux",
...
]
},
"hints" : {
"tree" : {
"separator" : "/",
"collapseAtLevel" : 2
}
}
}
]
}
}
}
Top-level README has "specificaiton" but should be "specification".
For this release, the only valid value for the key element is "self".
This part of the spec indicates that HAL-FORMS documents are only allowed to have one link.
To be backwards compatible, I think it would make sense to support multiple links. Or at least be optional.
If we could just tweak things so that it clearly states that templates operate on the "self" link.
sort out section numbers.
starting at 4.2.5 through 4.4.9 these sections should be indented one more level (4.2.4.1 -> 4.2.5.9?)
this has to do with the asciidoc generator (settinbgs or limits?)
There are some features missing from Hal-forms specification to be a complete hypermedia format.
One is to be able to determine the possible values for a field, for example, a select field with some options.
As pointed in the HAL mail list, there are three cases to support
(https://groups.google.com/d/msg/hal-discuss/bBi-i4FMdxk/8pzDwJFmAgAJ):
This metadata will be added per property in a new 'suggest' element.
Some samples of each case:
{"name":"priority", "value":"low", "prompt":"Priority",
"suggest": [
{"value":"low", "prompt":"Low"},
{"value":"med", "prompt":"Medium"},
{"value":"high","prompt":"High"}
]
}
}
{"name":"priority", "value":"low", "prompt":"Priority",
"suggest": {
“embedded” : "priorities",
"prompt-field":"desc",
"value-field":"id"
}
}
And in the same resource:
"_embedded": {
"priorities": [
{"id":"low", "desc":"Low", "longdesc": "Low priority..."},
{"id":"med", "desc":"Medium", "longdesc": "Medium priority..."},
{"id":"high", "desc":"High", "longdesc": "High priority..."}
]
}
{"name":"priority", "value":"low", "prompt":"Priority",
"suggest": {
"href" : “http://api.example.org/priorities”,
"prompt-field":"desc",
"value-field":"id"
}
}
And the response of the “http://api.example.org/priorities” call:
[
{"id":"low", "desc":"Low", "longdesc": "Low priority..."},
{"id":"med", "desc":"Medium", "longdesc": "Medium priority..."},
{"id":"high", "desc":"High", "longdesc": "High priority..."}
]
In addition I think that the name of the "suggest" property is not very understandable. Maybe "options" name inspired in HTML could be easier to understand from my point of view.
per Pete Johansen on list
The encoding for the request body in the case of POST/PUT is omitted... Assumed to only support application/x-form-urlencoded? Negotiated somehow? (Can a server send an Accept as a response header to indicate content types it would accept for a PUT/POST?)
Hi,
in my opinion a template should allow a list of content types instead of only one. Format maybe like the http accept header.
Is there any way to have a template define a list to which I can add and remove rows?
E.g. if the model looks something like this:
{
foo: [
{ bar: "baz" },
{ bar: "bazinga" }
]
}
I would need the ability to
foo
list.selectedValues
has the same purpose as value
. Both properties show the pre-filled value of the property before the user starts editing.
I hope we can remove selectedValues
and use value
for all these cases. If not, I think the spec could benefit from some clarification on how they relate to each other. What happens if both are provided?
This ticket in Spring HATEOAS makes obvious that the spec is currently not entirely clear which URI is to be assumed the default target for all state transitions described using templates.
The description of target
mentions that the value should be ignored if missing or invalid. However, it doesn't mention that it's the self link's value that should be used as target. Neither the description of the _links
element not the section of the _template
section explicitly state that either.
From the current draft (in the minLength chapter)
this attribute SHOULD appear along with the maxLength attribute
I'm not sure why minLength should appear when maxLength does and vice versa. I think there's legitimate reasons for each to appear without the other.
Is it possible to define required headers which need to be send along with the request using HAL-Forms?
Examples would be
Similar to #6, but instead of focusing on the presentation, I'd like to be able to specify the type of data expected in a field. From that a client could determine how best to present it. e.g. if the type is Date
a date picker could be presented, or, to borrow another example from #6, email
would hint to the client that on a mobile device the user should be presented with the email keyboard.
However, I'd like to go a step further and suggest json-ld, although I'm fairly certain that it wouldn't require explicit support (unlike #23 proposed for json-Schema). As an example, I have an API that requires an address, which is a nested object and being able to specify e.g. "dataType": "@context: http://schema.org/Address"
which would allow me to build intelligent clients that would know to find the component that knows how to render that particular schema. I think this can be achieved with a simple extension to the properties with a simple new optional property (I'm about to try that).
I'm curious why data type is not already included? It seems simple and obvious, which means I'm probably not considering something.
I'm currently implementing a REST api based on HAL. A big part of this is that we're serving both:
The HTML output is actually rendered by doing an internal request for HAL, and taking out the links, properties, etc. So it really kind of ends up being something like a HAL client, but built straight into the api itself.
The big thing I'd love to think about next is indeed forms. I have a few different ways I'm thinking about this. One of the ways is to actually just produce HTML forms statically on a case-by-case basis.
What I'd actually really like to do is make form-generation also an integral part of the API. HAL-FORMS might allow me to do this, but the big thing I'm missing is json-schema integration.
We're using json-schema for all our document-structure validation and provide links to it via a describedBy
relation type. If HAL forms supported it, I could straight up embed my json-schemas in a HAL-forms object and generate quite complex interfaces.
Right now I could potentially just try to map our json-schema to HAL-Forms, but it's a bit more minimal which means that it will be a bit of a lossy transformation and only the simplest schemas can be turned into forms.
So my question really is: have you ever considered doing this, or do you see reasons why it would be a mistake?
Thanks,
Evert
Basically we have tried to follow the proposed process flow approach in the spec and we didn’t found a solution to deal with, when the URL of the form definition is dynamic.
In other words, the current proposed approach uses the rel as a URL. It means that the clients must know the rel, (I guess that the rel must be static) and does not work properly when the form content is dynamic and changes constantly (this URLs can not be inside the client).
For instance in the following example we can see the URL to prepare the form for a specific order:
{
"_links": {
"self": {
"href": "http://api.example.org/orders/1",
},
"http://api.example.org/orders/1/prepare-edit": { ← url to obtain the hal-form
"href": "http://api.example.org/orders/1/edit",
},
}
}
One possible solution for this case, could be to use another approach where we have independent rels, one for form preparation and another one for the submit, for instance:
"_links" : {
...
"prepareForm" : {
"href" : "http://api.example.org/orders/1/prepare-edit" ← Url to create dynamic form
},
"submitForm" : {
"href" : "http://api.example.org/orders/1/edit"
}
}
This solutions works well but the client don’t see the relation between both rels in the HAL response. In addition within our requirements (related to security), and once we don’t have the action URL within HAL-FORM, we need to infer this relation in some way to validate the incoming submit using the form definition.
This relation between both rels can be useful as well when we want to define the FORM in HTML format. I mean once we define action URL within HAL (the default behaviour) we don’t need to define again when we define the form. It’s important to note that HAL founder Mike Kelly likes HTML based form definitions.
So we have been thinking in a more suitable approach where the client can understand the relation between both rels and any tool or library can infer the relation between both rels as well. Basically we think that type
property inside the link (from HAL spec) can be useful for that. For instance using this approach the HAL response:
"_links": {
"edit": [{
“type” : “application/prs.hal-forms+json”,
"href" : "http://api.example.org/orders/1/prepare-edit" ← Url to create dynamic form
},{
"href" : "http://api.example.org/orders/1/edit"
}]
}
The resulting hal-forms response:
{
"_links" : {
"self" : {
"href" : "http://api.example.org/orders/1/prepare-edit"
}
},
"_templates" : {
"default" : {
"title" : "Edit",
"method" : "put",
"properties" : [
….
]
}
}
}
In that way we solve both requirements. We can deal with dynamic URLs for form definitions and we can express the relation between both rels improving the readability for humans and tools processing for client and server sides.
What do you think about this approach? Do you think it could be included in the HAL-FORM spec suggested process flow as the standard way to deal with this kind of dynamic forms?
per MikeKelly onlist
Had you considered a mechanism whereby properties could populate their values from the state of the referring resource, via jsonPath or similar? (Something akin to hidden inputs in html forms.)
While working on the HAL FORMS implementation in Spring HATEOAS and collaborating with @toedter on the HAL Explorer there are a couple of observations that I'd like to share here.
A fundamental challenge in producing requests from filled out forms is deciding whether to send the value(s) selected as scalar value or array of values. I was under the assumption that the presence of any of the …Items
attributes indicates an array to be used, but Kai rightfully pointed to the spec unconditionally defaulting minItems
to 0 and maxItems
to unbounded. The implementation in HAL Explorer currently inspects maxItems
for the value of 1 and uses that as an indicator that we deal with a single-select and send the selected value as scalar one in e.g. a JSON request. That causes a few challenges:
…Item
attributes indicates the value to be send in "array fashion", whatever that looks like in the format accepted by the actual resource (e.g. { "field": [ … ] }
in plain JSON, { "_embedded" : { "field" : [ … ]} }
if the target requires HAL etc.)minItems
/maxItems` only apply if the property is a collection valued one, indicated by the presence of at least one of the attributes.That would allow clients to decide about the way the selected value(s) to be submitted based on the presence of the attributes alone. minItems
/maxItems
missing completely would indicate single select and scalar submission.
In an example project I returned HAL for the response of a resource pointed to by a link
attribute. I read this section of the spec in a way that fundamentally, the client should be able to work with any collection of scalar values or value
/prompt
pairs that the client can be made to work with. I.e. if the server returned a HAL flavored { "_embedded" : { "field" : [ … ] }}
and the client generally understands HAL, it should consume the field
array (more precise: just grab all keys within _embedded
and flat map concatenate them). Kai argued, that it's not quite obvious that this should be supported as the current working speaks about arrays and collections as the linked to examples only show raw JSON arrays.
Clarify that the exact format of the collection is defined by the media type returned by the server and maybe also show an example of something other than raw JSON. Remove the sentence that type
should be set to application/json
or text/csv
. This would e.g. allow also using resources that return other media types as long as they adhere to the general format (scalar values or value
/prompt
pairs).
I think that, HAL FORMS being an extension of HAL, we should make sure that the interaction models should also describe, how to behave with resources using HAL. Currently, under strict interpretation of the FORMS spec, we cause quite a bit of friction in terms of representations that have to be supported by servers. I.e. if I have a HAL based API and would like to extend that using HAL FORMS, I ideally would like to be able to use already existing resources and representations, or – if I need to create new ones – at least stick to the same media type for those resources so that clients already understanding by base media type allow seamless interaction with those resources.
The spec says about _templates.property.value
:
value : The parameter value. This is a valid JSON string
In line with this, the example hal-forms response has:
"properties" : [
{...},
{
"name" : "completed",
"required" : false,
"value" : "false", <-- JSON string
}
]
However, in the example app/json request the value is a JSON boolean:
{
"title" : "A Sample HAL Forms Response",
"completed" : false <-- boolean
}
Which one is correct? If both, how would the client know to convert the string to a boolean? My feeling is, _templates property.value
should be a JSON scalar.
Can we lift the restriction on contentType
and let it support, well, any media type?
People are wanting to create REST endpoints with Spring HATEAOS that can receive application/hal+json
on a PUT, and wondering why they can't put that in their HAL-FORMS documents under contentType
.
cross-ref query string registry values of HAL-FORMs properties and reconcile as needed.
current language in the spec says....
The _links element contains any links associated with the HAL-FORMS document. For this release, the only valid link object is the self link object.
it would be better to use SHOULD/MUST language and allow for other LINK values via a MAY clause.
The _links element contains an array of links associated with the HAL-FORMS document. Dcoument authors SHOULD/MUSt include a "self" link object in the collection. The links collection MAY also contain other link values. HAL-FORMS clients SHOULD ignore any link objects they do not understand and MAY reject a HAL-FORMS document that does not contain a "self" object.
or something like that.
I'm missing some types and would like to get some feedback if they might be implemented in the spec.
data:image/png;base64,...
. A client interface would render the image and a text input and / or a file upload.For further aid, I would also like to propose a new field on properties:
mimeTypes
which would be OPTIONAL and may contain an array of MIME-types. This would help clients to know which types for image
and file
are accepted.
add support for textarea
as part of the enumerated type
property and add rows
and cols
as OPTIONAL attributes of the property
object.
this brings HAL-FORMS into line to support HTML5-style multiline input boxes.
add outline numbers to indivisual attributes (not just top-level elements.
The specification of the _templates
collection is a bit odd. It lists all properties, including the key
property, when in fact – I think – key
is not an actual property, but the key of the dictionary of all templates. From the spec, you could think that a _templates
definition might look like this:
{
…,
"_templates" : {
"default" : {
"key" : "default",
"contentType" : …,
…
}
}
}
The reason you can get to this assumption is that key
is discussed on the same level as contentType
et al. and among all properties that can be used within a single template entry. Does it make sense to pull that discussion up into 3.2 to avoid this confusion?
There's still room for clarification in the required naming for multiple templates. Assume you have a single, logical template foo
. As per the spec, that needs to be named default
. If that resource evolves to support a second template bar
, would (should?) the list of template names change to foo
, bar
or stay with default
, bar
? The former might be disrupting to clients that look for default
only. The latter – and that renaming in general – mask the logical name for the advertised first transition.
This always seemed a bit weird to me. What's the original intention behind that "if it's one, it's got to be named default
" rule? I suspected that it was introduced to make it easy for clients to find "a default" template, but as the spec currently restricts the rules to the case of one template present only, it would be the single, canonical template anyway, wouldn't it? To convey those high-level semantics, I would expect using default
to be of even greater significance in the case of multiple templates, although you could argue that with a stable key ordering, clients could generally assume the first entry to be "the default one". I am not sure how common it is to rely on ordering of the keys within a JSON map, though. If it's not common, then staying with default
in the case of multiple templates available would kind of be required.
The current state of affairs complicates the implementation of the server as it's not obvious how to behave in case of multiple templates (see this ticket in Spring HATEOAS) for example. Anyone aware how other server libraries treat this?
As you already Suggested adding an optional field "RENDER" could help human-facing apps, as it provides hints on how to render the content. This is something we are missing, as we are starting to develop real apps. We should provide the possible values of the RENDER field.
i.e
per mike kelly on list:
the rel property seems redundant - doesn't the context URI provide this value already? Might it make sense to model this as a self link instead?
As promised, here's a list of things that I think would be very great to have in HAL-Forms.
If it's more helpful to have these all as separate issues, I'm happy to split these up.
_htarget=
query parameter doesn't make that much sense. URIs are largely treated as opaque, and forms are server-rendered based on other contextual information.type
property in each field, maybe just referencing the HTML5 specification for it's possible values. Also mentioned in #6. It might be helpful to mention what each 'type' serializes to. For example, a checkbox
will probably generate a JSON boolean.placeholder
, min
, max
, step
, minLength
, maxLength
enum
or options
property. options
could be used as follows:{
"name": "color",
"options": {
"#F00": "red",
"#0F0": "green",
"#00F": "blue"
}
}
default
). Also mentioned here #24I believe all of these could be introduced without breaking backwards compatibility.
If it's helpful, the type Ketting uses to generically describe a field in a hypermedia document is here:
https://github.com/badgateway/ketting/blob/master/src/field.ts
This is how we map a HAL Forms field to Ketting field:
https://github.com/badgateway/ketting/blob/master/src/state/hal.ts#L266
In the current specification there is only a valid template per hal-forms response.
It is interesting to have multiple template support.
The missing piece is how to link each template with its link.
I can imagine a working example like this one:
{
"_links" : {
"self" : {
"href" : "http://api.example.org/filter"
},
"edit" : {
"href" : "http://api.example.org/edit"
}
},
"_templates" : {
"default" : {
"title" : "Filter",
...
},
"edit" : {
"title" : "Edit",
"method":"put",
...
}
}
}
Where the template 'default' always uses the link with rel 'self' and the rest of templates will use a link with the same name (template 'edit' and link 'edit' for example) or 'self' as fallback.
We use HAL because we like using links. Aside from the 'discovery' benefit, we heavily use links to express relationships between entities. For example, a blog article
might have many category
links.
The majority of the cases where we will be using the new options
feature is to let users specify these relationships (let a user select a category when writing an article).
The ability to use a link to specify the source for the dropdown is helpful but has some drawbacks. We would like to be able to select the 'source' for a property by specifying:
rel
.For example, in the article category case we'd want to point to a 'categories' collection and the 'item' rel.
{
name: 'category',
type: 'uri',
options: {
link: { href: '/category' },
rel: 'item
}
}
What does this give us:
I feel that this is a very natural fit for HAL Forms and HATEOAS in general.
Is it possible to define properties which accept arbitrary key/value pairs? For example when the server accepts a Map as request body.
Like properties: * or so...
POST /foo
key1=value1&key2=value2,...
Might as well open a ticket for this, as it's something that was discussed in various other threads.
I think it would be great if we can explicitly encode numbers and booleans as numbers and booleans when encoding to application/json
, including having the ability to encode 'an array of numbers or booleans' for the "multiple" cases.
Hi @mamund,
Thanks for the interesting spec!
Have you considered how to represent different field types; e.g.
At the risk of asking for too much...
We use links for relationships. It's not unusual therefore for a user to select a related resource for something they are editing,
For example, a user is writing a blog article. One of the fields is a 'category'. Categories are expressed as link relationships and are separate resources.
It would be really nice if we can point a property to a 'category' collection, fetch a list of categories and use it to populate a <select>
field. We have a couple of heuristics for determining the title for any given resource.
Mentioned in a few different threads, but I think it deserves its own issue.
When an 'options' property is present on a property, it potentially allows the selection of more than one item.
In JSON, if multiple are selected, this gets encoded as an array of strings.
It would be helpful for our implementation if we can add an additional multiple
property on the options object.
If multiple
is set to true:
minItems
and maxItems
are allowed to be set.value
and selectedValues
should be an array.If multiple
is set to false, or omitted (the default)
minItems
and maxItems
are ignored/forbidden.value
and selectedValues
should be a string.https://rwcbook.github.io/hal-forms/#_code_type_code
"Possible settings for the type value adn teh expected contents to be returned inthe are:"
Should be?:
"Possible settings for the type value and the expected contents to be returned in here are:"
I do not understand how to use templated property values.
- +templated+ : Indicate whether the +value+ element contains a https://tools.ietf.org/html/rfc6570[URITemplate] string for the client to resolve. This is a valid JSON boolean. This is an OPTIONAL element. If this element is missing, set to empty, or contains unrecognized content, it SHOULD be treated as if the value of +templated+ is set to `false'.
Example:
"_templates" : {
"default" : {
"title" : "Create",
"method" : "post",
"contentType" : "application/json",
"properties" : [ {
"name" : "widget",
"value" : "http://example.com/{foo}/path/{?bar*}",
"templated" : true
}]
Is the idea to send a URL to the server?
Ah - afterthought: maybe the value can be exactly one template variable:
"_templates" : {
"default" : {
"title" : "Create",
"method" : "post",
"contentType" : "application/json",
"properties" : [ {
"name" : "wassacominago",
"value" : "{bar*}",
"templated" : true
}]
So, if the client had a list of wassacominago,
var wassacominago= ["bar1", "bar2", "bar3"]
it would construct
wassacominago=bar1,bar2,bar3
Is that what it's for?
While type
can guide the client which type of input to render, this still leaves room on how to render the value.
For example a number
can have a different number of digits after the decimal point, or should be padded with 0
s.
A datetime-local
might be displayed just as a date when it is readOnly: true
, but with time when editing the value.
In contrast to the placeholder
this is not intended to be displayed to the user, but for the rendering of values.
So I'm proposing new OPTIONAL Property Elements
displayFormat
is a string that instructs the interface how to render a value that is not in edit mode (maybe because it is read only).editFormat
is a string of the same format, but is used when editing the value.If a client does not support these elements, it can just render the value as if they where not present.
As I have a strong .Net background, I propose those formats to be possible values (There is also an npm package implementing the same format clr-format):
"{0:N2}"
, value: 1234.567
, browser-locale: en-us
=> "1,234.45"
"{0:F1}"
, value: 1234.567
, browser-locale: de-de
=> "1234,5"
"Foo {0} Baz"
, value: "Bar"
, browser-locale: doesn't matter
=> "Foo Bar Baz"
However I'm open minded of the structure of the string.
From the HAL draft, only I have made non-IANA rel links into extension rels:
{
"_links": { ...
},
"_embedded": {
"orders": [{
"_links": {
"self": { "href": "/orders/123" },
"ex:basket": { "href": "/baskets/98712" },
"ex:customer": { "href": "/customers/7809" }
},
"total": 30.00,
"currency": "USD",
"status": "shipped",
},{
"_links": {
"self": { "href": "/orders/124" },
"ex:basket": { "href": "/baskets/97213" },
"ex:customer": { "href": "/customers/12369" }
},
"total": 20.00,
"currency": "USD",
"status": "processing"
}]
The suggested hal-forms flow seems to allow only one hal-form for ex:basket and ex:customer, for both /orders/123 and /orders/124, even though they appear repeatedly. Do I interpret that correctly?
to handle all the new elements of a property
item, move it up a level in the doc.
add numbering to the doc
key - The unique identifier for this template object. This is a REQUIRED element. For this release, the only valid value for key is "default". If this element is missing, set to empty or is unparsable, this template object SHOULD be ignored.
Right now, the spec says that the ONLY template allowed is the default one. Can we revise the spec to read that "default" is the, so far, the only pre-defined one? This would support the ability to have multiple templates.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.