Skip to content

API to register a listener for processes #5913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ebruchez opened this issue Jul 27, 2023 · 11 comments
Closed

API to register a listener for processes #5913

ebruchez opened this issue Jul 27, 2023 · 11 comments

Comments

@ebruchez
Copy link
Collaborator

ebruchez commented Jul 27, 2023

Scenario: embedding/component would like to know when a save process has run. The ability to register a callback function or listener would make sense via the JavaScript embedding API, rather than dealing with global functions.

@ebruchez
Copy link
Collaborator Author

Suggestion:

ORBEON.fr.API.addProcessCallback(fn: (name: string) => ())

ORBEON.fr.API.removeProcessCallback(fn: (name: string) => ())

Implementation:

We don't want every process to call back a client-side API. This would allow the client to obtain knowledge that only the server should have, for security reasons. We we need a process to be explicit about it.

Possibilities:

  • a public entry point, like: ORBEON.fr.API.callProcessCallback, called from navigate("javascript:")
  • a private entry point, which would be called with a specific process action like callClient()

@ebruchez
Copy link
Collaborator Author

+1 from customer

@ebruchez
Copy link
Collaborator Author

ebruchez commented Aug 8, 2023

The API needs to deal with listeners at the level of a given form.

Currently, embedForm() returns a Promise[Unit]. This only means that the embedding of HTML and CSS and JavaScript succeeded. But form initialization might not yet have happened.

Listeners should be associated with an instance of xforms.Form. But how to find this instance after calling embedForm()?

initializeFormWithInitData() is called as a side-effect of loading JavaScript files. It makes sure all the markup in the page is ok pageContainsFormsMarkupF, and then calls initializeForm() which returns an xforms.Form. How to connect all those parts?

@ebruchez
Copy link
Collaborator Author

ebruchez commented Aug 8, 2023

EmbeddingSupport.loadScripts() should complete once the loaded JavaScript have not only been loaded, but parsed and run. This means that initializeFormWithInitData() has also been called.

Presumably, with embedding, pageContainsFormsMarkupF should already be complete at that time, but maybe not, and in any case the completion of that Future can be asynchronous. This means that initializeForm() might not have been called yet.

@ebruchez
Copy link
Collaborator Author

ebruchez commented Aug 8, 2023

Ok now we have a way to receive a Promise[Form] from embedForm(). Now this is at the XForms level. Should we return something like an fr.Form instead? And then what should the API be:

  1. On the client
  2. On the server (actions)

Option 1:

  • XForms level
  • client registers callback by name
  • server process action: xf:callback() or similar

Option 2:

  • Form Runner level
  • client registers "process callback"
  • server action: notify-client() or just callback()

Any other ideas?

@ebruchez
Copy link
Collaborator Author

ebruchez commented Aug 9, 2023

  • Promise[Form]
  • decide on API
  • consider also supporting extra parameters
    • Postpone, see other comments.
  • complete implementation
  • doc
  • test
  • cherry-pick on custom branch

@ebruchez
Copy link
Collaborator Author

Passing parameters is not a P1, but if we wanted to do it, how would we?

  1. We could consider any extra parameter to be a parameter to pass to the function.
    • benefit: use current action syntax
    • drawbacks
      • can't name a parameter name
      • parameters are named, but why?
  2. We could consider that parameter names will become keys in a JavaScript object passed to the callback.
    • benefit: use current action syntax
    • drawbacks
      • can't name a parameter name
      • parameter names make sense
  3. We could update the process syntax to allow passing arrays.
    • benefit: needs update to action syntax
    • drawbacks
      • any valid JavaScript name is possible
      • parameter names make sense

Example of 1 and 2:

callback(name = "my-callback", foo = "...", bar = "...")

Example of 3:

callback(name = "my-callback", parameters = ["...", "...", ...])

@ebruchez
Copy link
Collaborator Author

RESOLUTION: For now, don't support parameters.

@ebruchez
Copy link
Collaborator Author

@ebruchez ebruchez self-assigned this Aug 16, 2023
@ebruchez
Copy link
Collaborator Author

Related to parameters, I notice that our process xf:dispatch(), xf:show(), and xf:hide() do pass parameters (equivalent to xf:property) by taking all the parameters with names that are not used by the action (name, targetid, and dialog).

ebruchez added a commit that referenced this issue Aug 17, 2023
ebruchez added a commit that referenced this issue Aug 17, 2023
- move to Scala
- use more explicit method names and reorganize
- add `getForm()` API
- add `isFormDataSafe()` API
ebruchez added a commit that referenced this issue Aug 21, 2023
@ebruchez
Copy link
Collaborator Author

ebruchez commented Aug 30, 2023

  • backport to 2022.1-pe, or custom branch

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

No branches or pull requests

1 participant