launchpad-dev team mailing list archive
-
launchpad-dev team
-
Mailing list archive
-
Message #01680
Re: Redesigning lazr.restful support for AJAX
On 09-11-16 06:06 PM, Francis J. Lacoste wrote:
Hi Leonard,
During last week lazr-js sprint, we come out with a lot of issues around the
current way we return HTML fragments from the web service. Initially, we
thought that we needed to support HTML representation from named operation
(filed as https://bugs.edge.launchpad.net/lazr.restful/+bug/480192) but after
consideration, it turns out that this isn't sufficient.
Here are the constraints that we need to solve to make lazr.restful really
useful in an AJAX environment.
1) We want to be able to retrieve one or multiple page fragments after making
a model change through the web service (either PATCH or named operation).
(For example, subscribing a user means that maybe two or three parts of the
page will need to be updated.)
Does anyone have any other examples of when this would be useful?
So, here is what I understand about the problem so far:
The subscribers list sounds easy at first pass: for the initial page update,
return a <ul> with the <li> elements already formatted as we need them:
<ul>
<li><a ...>Foo Person</a></li>
<li><a ...>Bar Person</a></li>
</ul>
For updating the subscribers list, like "add subscriber foo", you need to call
the "add subscriber" webservice method, and tell it to return not just the
formatted subscriber name, but what else?
Also, in the subscriber case, arranging the page in JavaScript is also not a big
deal.
I guess the problem is when you don't want simple HTML, like a bug subscriber.
Instead, one of the problems is when you want complex context-specific markup,
like a bug comment. Bug comments objects have a fair number of fields
associated with them, and the HTML nodes in the comment need to be arranged in
the correct order to get the page presentation right. It would be a real pain
to arrange the arbitrary pieces into the correct layout using JavaScript. A
page fragment would be much easier.
2) We want to reuse the presentation logic already coded in the regular web UI
views.
(We already have views that know how to render the different parts that
needs to be updated on the page.)
3) We want to provide a very productive API for front-end developers to use.
(Minimize amount of web-service specific glue needed, minimize the amount of
confusing asynchronous requests that needs to be done).
So one solution we found out was to basically drop the way HTML representation
are currently implemented for something much simpler and much more powerful.
Instead of wiring server-side one-to-one individual web-service resources to
an HTML representation, we should basically let the AJAX client decide what
should be returned from the web service call.
The client would request that one or more views be rendered after the
successful completion of the API call and their results returned to the
client.
We could use the accept-extension to the Accept header to specify the list of
views to return results.
Something like:
Accept: application/x-page-fragments;views="subscribers=+subscriber-portlets,
count=+subscribers-count"
That should return a JSON dictionary containing two keys: subscribers
containing the result of the +subscriber-porlets view and count containing the
result of the +subscribers-count view.
That removes the wiring that has to be done now server side to map these
existing views to the HTML representation of fields, removes the problematic
limitation of having only HTML representation and allows us to retrieve
efficiently all the fragments we need on the page.
I assume you are calling the webservice as you would normally, but you are
adding your special Accept header?
If that is the case, then it still feels a bit strange. You are taking the API
model and namespace, and mapping that onto a set of page fragment names.
However, this set of fragments actually represents the Launchpad website URL
model, not the API model. You are telling the webservice "Get me a bug comment,
but using this magic word, return it to me as it would appear on the page at
/+bugs/1234/."
If you want a real loop, look at it this way: you map the database model to the
webservice WADL addresses, and you map the database model to the website URL
addresses. URLs are rendered by views. OK. We are suggesting that views are
also rendered by Fragment Names. Also OK. But then we are say that to call the
Fragment Name, you have to know the correct address, and that address is an
object picked out of the WADL? Why not use the address you already have, that
being the URL of the page you are currently visiting?
Instead of mapping one namespace onto the other, could we just call the current
page address to fetch the fragment? Y.io("?fragment=A&fragment=B"). I guess
this is the +fragments solution Aaron pointed to? What exactly are the problems
with it?
Maris
Attachment:
signature.asc
Description: OpenPGP digital signature
Follow ups
References