HAL-FORMS: Process flow for editing an embedded resource out of a list.

177 views
Skip to first unread message

Philipp Kühn

unread,
Nov 3, 2021, 6:14:17 PM11/3/21
to HAL Discuss
My basic flow is like this:
Home has links to different resource lists
A list endpoint contains _embedded resources with some properties to display in a table and a self link which is used to view or edit the full resource
An edit endpoint where the user comes to when dereferencing one of the self links

Now instead of guiding the user to a HAL resource through the self link, I would like to guide him to a HAL-FORMS resource so the UI knows how to render the form which is used to edit the resource.

From the example I get that the rel should be the URL to the HAL-FORMS document, but obviously "self" is not a valid URL.

What is the suggested approach here?
1. Just return a HAL-FORMS response on the "self" link if the ACCEPT header contains "application/prs.hal-forms+json"?
2. Add another link rel like "https://api.example.org/edit" with a href that is the same as the "self" link?
If yes, how would the UI know that this is used to edit the resource? Should the UI compare the href of the links and see they are the same, or do we need to introduce a tight coupling here so the UI will always use the "https://api.example.org/edit" rel as the link to the resource?
3. Add the "https://api.example.org/edit" rel on the edit page itself, forcing the UI to make 2 calls instead of one to display the edit form and maybe also introduce some tight coupling as mentioned above?
4. Something I completely missed?

mca

unread,
Nov 4, 2021, 11:02:10 AM11/4/21
to hal-d...@googlegroups.com
the HAL-FORMS docs here on suggested workflow [1] might help

HUMAN-DRIVEN APPS
here is what i am doing right now in the HAL/HAL-FORMS space for human-driven client apps:

- code client apps to request (and parse) HAL documents
- code clients to look for REL values in a HAL document that are valid URLs.
- if the REL is a valid URL, the client makes a call to that URL using the HAL-FORMS media-type string in the ACCEPT header
- if the server returns a 4xx/5xx, just move along
- if the server returns a 200, parse the HAL-FORMS into a client-side form. this might be displayed immediately or hidden behind a UI button, etc.

note that i don't depend on understanding the REL value ("edit", "collection", "item", "hatsize". etc.) here. I just process the doc and any forms i get, ready to present as UI.

MACHINE-DRIVEN APPS
for machine-driven apps, i DO code the client to "memorize" the REL values that are important to the app. that means I need the server to give me a complete list of all the possible REL values i might encounter. i then write a machine app to understand the RELS important to me (both data and actions) and code the client to look for these and act accordingly. for example it might look like this (in hyperLANG [2])

GOTO WITH-URL https://api.example.org ACCEPT application/vnd.hal+json
GOTO WITH-REL collection
ACTIVATE WITH-FORM http:s//api.example.org/forms/create-user WITH-DATA {"givenName":"Mark","familyName":"Morkelsen"}
GOTO WITH-REL item
ACTIVATE WITH-FORM https://api.eample.org/forms/update-user WITH-DATA {"nickName":"mork"}
GOTO WITH-REL home
EXIT

hope this helps.



Mike Amundsen



--
You received this message because you are subscribed to the Google Groups "HAL Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hal-discuss...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/hal-discuss/b4673162-a4c7-4403-b6f5-2dbb0e83095en%40googlegroups.com.

Philipp Kühn

unread,
Nov 4, 2021, 5:15:37 PM11/4/21
to HAL Discuss
Thanks for the clarification!

Is my understanding correct, that this approach effectively doubles the round trips to the database (if no caching is in place)?
First to get the HAL representation of the resource and a second time to get the HAL-FORMS representation to fill in the "value" properties.

How should a human driven UI decide whether to display a form immediately or hide it behind a button?
I'm thinking about the difference between an edit form on its own page and a button "create new" on a list view.

mca

unread,
Nov 4, 2021, 5:28:50 PM11/4/21
to hal-d...@googlegroups.com
comments below...

On Thu, Nov 4, 2021 at 5:15 PM Philipp Kühn <wer...@gmail.com> wrote:
Thanks for the clarification!

Is my understanding correct, that this approach effectively doubles the round trips to the database (if no caching is in place)?
First to get the HAL representation of the resource and a second time to get the HAL-FORMS representation to fill in the "value" properties.
in my case the API server doesn't need to talk to the database to serve up HAL-FORMS information. the forms are served from files on disk and are not filled in w/ context values (the client does that part). implementations may vary, of course. would be interested in how you are solving this problem.
 
How should a human driven UI decide whether to display a form immediately or hide it behind a button?
I'm thinking about the difference between an edit form on its own page and a button "create new" on a list view.
that's up to the consuming app. as a general rule i display links/buttons first and force the human to click on something to see the form. esp on small screens like phones.

cheers
 

Philipp Kühn

unread,
Nov 4, 2021, 6:08:05 PM11/4/21
to HAL Discuss
> the forms are served from files on disk and are not filled in w/ context values (the client does that part).
Under  3.3.1.7. value, the specification states:
"If it does not exist, clients SHOULD act as if the value property is set to an empty string."

So filling in the values from the previous HAL response seems invalid according to the spec.


>  that's up to the consuming app. as a general rule i display links/buttons first and force the human to click on something to see the form. esp on small screens like phones.
I'm thinking about building a tabbed interface if the link to the form has the same href as the resources self link and displaying links/buttons if the href is different. Might work, will come back later and let you know about my experience :)

futy...@gmail.com

unread,
Nov 12, 2021, 9:16:42 PM11/12/21
to HAL Discuss
My first reaction was: no, the self link shouldn’t return different resources like HAL and HAL-FORM.
After I think a bit more I think the solution 1) in original message actually is the right one.
Both HAL and HAL-FORM are different representation of the same resource. So, the same “self” link should return both depend on the format (MIME-type) requested.

Philipp Kühn

unread,
Nov 13, 2021, 5:43:42 PM11/13/21
to HAL Discuss
I'm currently trying to implement a HAL-Forms server and Client.
The more I'm programming, the more I come to the insight that the spec is a little bit unclear how to present the form to the user if the value of a property is missing or empty.

As stated above, the spec states that it should be treated as an empty string.
However from the example it looks as if the client must fill in the values from the previous HAL response (The one that contained the link to the resource).
Implementing it that way, the client could cache the form and reuse it.
This would mean, that we need at least 11 requests to display 10 resource (1 FORM and 10 HAL)

But if you closely follow the spec, you must send different  forms (or the same form, but with different values) for each resource.
This would mean, that we need at least 20 requests to display 10 resource (10 FORM and 10 HAL)

However if you follow solution 1) and implement the server in such a way that the same endpoint can server HAL and HAL-Forms and the client would always request HAL-Forms,
you only need at least 10 requests to display 10 resources (10 FORM).

So I'm also seeing that they both are just different representations of the same resource and the client should request whatever it needs.
This will probably boil down to having clients without user interaction using HAL while clients that display an UI would use HAL-Forms.

At the moment I'm implementing it using the 20 requests as this is closest to the spec, although I do not really like it.

mca

unread,
Nov 13, 2021, 8:06:13 PM11/13/21
to hal-d...@googlegroups.com
good to see your note. happy to hear your are working on a HAL-FORMS implementation. your feedback here is helpful.

my responses inline...

On Sat, Nov 13, 2021 at 5:43 PM Philipp Kühn <wer...@gmail.com> wrote:
I'm currently trying to implement a HAL-Forms server and Client.
The more I'm programming, the more I come to the insight that the spec is a little bit unclear how to present the form to the user if the value of a property is missing or empty.

As stated above, the spec states that it should be treated as an empty string.
However from the example it looks as if the client must fill in the values from the previous HAL response (The one that contained the link to the resource).
the spec does not say you MUST fill in. this is a choice you can make as a developer. same as HTML forms, XFORMS, etc.

Implementing it that way, the client could cache the form and reuse it.
This would mean, that we need at least 11 requests to display 10 resource (1 FORM and 10 HAL)
yes, i typically use caching headers to make this easier for HTTP clients. note that this caching does not require any special programming on the client side since browsers and most HTTP libraries can be used in ways that honors caching directives from servers. 

it does, however, mean client-side apps could fill in the inputs of the form based on the selected record on the client side. if that's messy there is a section in HAL-FORMS (Query Strings) that gibes some examples on how to help the server fill things out ahead of time. naturally, that means abandoning the caching features, tho.

But if you closely follow the spec, you must send different  forms (or the same form, but with different values) for each resource.
again, the spec does not address this - at least it is not *meant* to address this point. if you can show where this is in the spec that would help clear up this point.
 
This would mean, that we need at least 20 requests to display 10 resource (10 FORM and 10 HAL)
often, my services have multiple forms for the same resource (edit, delete, edit a subset of fields, add a dependent record, etc.) so a single resource might have several associated forms. the numbers can get quite large if you have designed a system that supports more than one record<g>. in my case, there are also forms related only to the collection cases. like searching (i commonly have multiple search forms for the same list collection) and adding new records to the collection. so, if you do that math, a list of 10 records could easily mean the potential to call up 40-50 form instances to cover all possible cases. again, this is the same for other form systems -- nothing special here.

BTW - just took a break and checked out a repo that shows some HAL-FORMS use and i have 16 different forms defined on disk -- without accounting for any filling in of values. the app has hundreds of records, soo......

However if you follow solution 1) and implement the server in such a way that the same endpoint can server HAL and HAL-Forms and the client would always request HAL-Forms,
you only need at least 10 requests to display 10 resources (10 FORM).
 
 

So I'm also seeing that they both are just different representations of the same resource and the client should request whatever it needs.
This will probably boil down to having clients without user interaction using HAL while clients that display an UI would use HAL-Forms.

At the moment I'm implementing it using the 20 requests as this is closest to the spec, although I do not really like it.
again, don't let the spec tell you how to program your client-server interactions. feel free to be inventive, creative, or just plain sneaky<g>. i created an app a while back that loaded all the form templates at startup (i scanned all the keys for URIs and pinged the server for any forms), kept them in memory, and then served them up on the client side as filled in forms whenever the user clicked in the right place.  

love to learn more about what you're working on and how HAL-FORMS can be improved.

cheers.

Philipp Kühn

unread,
Nov 14, 2021, 10:25:36 AM11/14/21
to HAL Discuss
Thanks for the reply :)

> the spec does not say you MUST fill in. this is a choice you can make as a developer. same as HTML forms, XFORMS, etc.
If you define a <input type="text" value="foo" /> The browser will render the value defined in the text box.
As written above, under  3.3.1.7. value, the specification states:
"If it does not exist, clients SHOULD act as if the value property is set to an empty string."
I read this as: "If the value is missing, a blank input field SHOULD be rendered. If you try to follow the spec closely, a SHOULD becomes a MUST. So if the value is empty, I MUST NOT fill in any value into the input field.

Do you have an example app running somewhere that I could have a look at?

I'm developing RESTworld.
It is meant as a Framework to support an ASP.Net Core Backend with Entity Framework and an Angular Frontend.
It is meant to provide an easy way to implement a lot of CRUD style operations.
So for every Table in the database, I have CRUD endpoints + a List endpoint.
NuGet packages can be found here:
npm packages here
Github repositories here

mca

unread,
Nov 14, 2021, 1:31:06 PM11/14/21
to hal-d...@googlegroups.com
inline...


On Sun, Nov 14, 2021 at 10:25 AM Philipp Kühn <wer...@gmail.com> wrote:
Thanks for the reply :)

> the spec does not say you MUST fill in. this is a choice you can make as a developer. same as HTML forms, XFORMS, etc.
If you define a <input type="text" value="foo" /> The browser will render the value defined in the text box.
As written above, under  3.3.1.7. value, the specification states:
"If it does not exist, clients SHOULD act as if the value property is set to an empty string."
this is meant to allow cases where servers don't send fields and clients are expected to not "crash" or reject the response w/ an error. 
 
I read this as: "If the value is missing, a blank input field SHOULD be rendered. If you try to follow the spec closely, a SHOULD becomes a MUST.
well, that's certainly an interesting interpretation. "a SHOULD becomes a MUST" kinda makes the whole RFC2119 a joke, right? does MAY become SHOULD, too?
 
So if the value is empty, I MUST NOT fill in any value into the input field.
um, that is the point right? i mean if you don't have a value, you shouldn't be making things up, right?

or are you deciding that since the *form* was not sent w/o a value then the client is not allowed to supply a local value when rendering that form? i mean, you can decide that but nothing in the spec requires that and it seems needlessly cruel to human users<g>. 


Do you have an example app running somewhere that I could have a look at?
there is a minimal browser SPA associated with that service:  https://rwcbook08.herokuapp.com/files/hal-client.html

IIRC, there are some HTTP/HTTPS challenges on the hosted heroku running sample. you proly need to pull that repo down and run the nodejs version locally to get it all working. 

cheers

Philipp Kühn

unread,
Nov 15, 2021, 5:53:23 PM11/15/21
to HAL Discuss
Thanks for the links, these cleared up some things for me.
I found out, just using http instead of https for the herokuapp SPA makes it work.
Although i got a lot of 404s when navigating the app, one of the most important parts, I found out was that you are using placeholder values, like {id}, {name} and so on as values for your forms.
This is the indicator for your app to fill in the values of the previous HAL response.
I think, this is a very important part and this should be covered in the spec if it is intended to be the way how clients should fill in the form templates.
Otherwise people might just implement different interpretations of how values should be filled in (as you can see above, my first assumption was that an empty value was the indicator to fill in the values of the previous HAL response).

>  well, that's certainly an interesting interpretation. "a SHOULD becomes a MUST" kinda makes the whole RFC2119 a joke, right? does MAY become SHOULD, too?
Of course, RFC2119 is not a joke ;)
If you look at section 3, it states:
"SHOULD This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course."
As I have not found any valid reasons to not follow the HAL-Forms spec (my whole motivation is, creating a client that implements the spec as good, as possible so it can be reused across projects), according to RFC2119 I'm not allowed to choose a different course.
Of course I could say that I'm not implementing a particular part of the spec, but that is not my goal, as long as it is possible.

mca

unread,
Nov 15, 2021, 7:56:12 PM11/15/21
to hal-d...@googlegroups.com
inline...


On Mon, Nov 15, 2021 at 5:53 PM Philipp Kühn <wer...@gmail.com> wrote:
Thanks for the links, these cleared up some things for me.
I found out, just using http instead of https for the herokuapp SPA makes it work.
Although i got a lot of 404s when navigating the app, one of the most important parts, I found out was that you are using placeholder values, like {id}, {name} and so on as values for your forms.
This is the indicator for your app to fill in the values of the previous HAL response.
I think, this is a very important part and this should be covered in the spec if it is intended to be the way how clients should fill in the form templates.
Otherwise people might just implement different interpretations of how values should be filled in (as you can see above, my first assumption was that an empty value was the indicator to fill in the values of the previous HAL response).
this is not meant to be part of the spec. it's a local solution

Philipp Kühn

unread,
Nov 16, 2021, 5:33:15 AM11/16/21
to HAL Discuss
I know that it is not part of the spec.
But by making it (or something else) part of the spec, it would give developers a guidance on how implement forms that can be cached locally and reused.
Without any guidance, each developer has to come up with his own local solution which makes it impossible to cover all corner cases and develop a "universal" HAL-Forms client.

mca

unread,
Nov 16, 2021, 8:01:13 PM11/16/21
to hal-d...@googlegroups.com
inline


On Tue, Nov 16, 2021 at 5:33 AM Philipp Kühn <wer...@gmail.com> wrote:
I know that it is not part of the spec.
But by making it (or something else) part of the spec, it would give developers a guidance on how implement forms that can be cached locally and reused.
people are free to use it w/o it being in the spec.  if you'd like to implement it and write it up as an extension, that'd be fine.
 
Without any guidance, each developer has to come up with his own local solution which makes it impossible to cover all corner cases and develop a 
"universal" HAL-Forms client.
 feel free to write up your own guidance documents to share w/ others. the spec need not be the only voice on how to best use HAL-FORMS. 

Philipp Kühn

unread,
Jan 14, 2022, 10:51:30 AM1/14/22
to HAL Discuss
After some time, I finally finished my HAL-Forms implementation.
Reply all
Reply to author
Forward
0 new messages