Skip to content
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

Integrate ODK Web Forms prototype with functioning form submissions #2074

Open
spwoodcock opened this issue Jan 9, 2025 · 3 comments
Open
Labels
effort:high Broader scope task with unclear timeline (consider splitting) enhancement New feature or request frontend Related to frontend code priority:high Should be addressed as a priority

Comments

@spwoodcock
Copy link
Member

Is your feature request related to a problem? Please describe.

  • ODK Collect usage is clunky in FMTM - too much app switching.
  • We want to replace this with ODK Web Forms

Describe the solution you'd like

  • Initially we can run this in parallel to ODK Collect.
  • Have two options: 'Open in browser' (web form popup), 'Open in ODK Collect' (existing functionality).
@spwoodcock spwoodcock added effort:high Broader scope task with unclear timeline (consider splitting) enhancement New feature or request frontend Related to frontend code priority:high Should be addressed as a priority labels Jan 9, 2025
@spwoodcock
Copy link
Member Author

How Web Forms Work Currently

After digging into getodk/web-forms, we can see that the OdkWebForm Vue component is the intended entry point to using Web Forms.

For example (see the XForm XML is added as a prop):

<OdkWebForm
	:form-xml="formPreviewState.formXML"
	:fetch-form-attachment="formPreviewState.fetchFormAttachment"
	:missing-resource-behavior="formPreviewState.missingResourceBehavior"
	@submit="handleSubmit"
/>

The OdkWebForm component has three main parts: header, QuestionList, submit button.

QuestionList is where the actual questions are rendered:

<template v-for="node in nodes" :key="node.nodeId">
	<template v-if="node.currentState.relevant">
		<!-- Render group nodes -->
		<FormGroup v-if="isGroupNode(node)" :node="node" />

		<!-- Render repeat nodes -->
		<RepeatRange v-else-if="isRepeatRangeNode(node)" :node="node" />


		<!-- Render leaf nodes like string, select, etc -->
		<FormQuestion v-else-if="isControlNode(node)" :question="node" />

		<ExpectModelNode v-else :node="node" />
	</template>
</template>

Possible Approaches

  • Web component wrapper for Vue OdkWebForm, see a working example of this here.
  • iFrame of a Vue app rendering Vue OdkWebForm, where we inject in the form XML.
  • Re-write of OdkWebForm and all components using a Web Component framework like Lit.

A re-write could be a lot of work (let’s assess it…), so I’m leaning more towards a web component wrapper for the Vue OdkWebForm component.

Custom Question Components

However, we also have a parallel concern, around adding custom question types.

There are two approaches I can think of:

  • Somehow, we need to expose an interface where we can register alternative components that render for a given question type. Perhaps this is needed in QuestionList?
  • The fourth option not listed above is to manually build this specific form we need for the project (most likely just using the web-components xform-engine package). It’s the least useful approach generally, as it means writing specific code for the form questions needed by MdP. But it would simplify the requirement for custom question types (e.g. a ‘select an icon’ multiple choice question).

Where should we go from here?

  • @DanielJDufour is going to do some testing of the Vue components.
  • Keeping both requirements listed above in mind, do you have any thoughts about the listed approaches, other possible ways we could do this?

The perfect solution

Just a quick note to say IMO, the perfect solution would:

  • Allow for customisation of the component used to render specific questions, perhaps by exposing an interface of some kind in the Web Form library (I will talk with the ODK team and see if this is desirable).
  • A Web Components of some kind! Of course I would love the Web Forms library to be Web Components to start with... but failing that, we could fall back to wrapping the Vue component in a Web Component if necessary.

@DanielJDufour
Copy link
Contributor

@spwoodcock , great write up! I concur with most of what's being said. Because of the tight timeline, I vote for the following:

Phase 1:

  • Contribute extensibility to OdkWebForm. There's a lot of different valid ways to do this well, but I think an ability for a client to "register" and then use a custom question type is key to widespread adoption of Web Forms. Happy to keep it marked as "experimental" for the first phase. We could had it behind a feature flag or keep it an experimental fork.
  • Wrap OdkWebForm in a Web Component. If this hasn't been done by ODK team already, we could quickly implement a Web Component that just works for FMTM.

Phase 2:

  • Contribute experimental extension system to OdkWebForm once we've had time to try it out and see how it works for other potential implementors/projects.
  • Pull the custom web component out of the FMTM code base and make it more generally applicable, including outside of FMTM.

Phase 3:

  • Perhaps contribute a deeper refactor of some of the form rendering logic, converting the core logic to using web components and then having Vue or Svelt as higher order wrappers on top of that.

Recognizing I was sorta pushing for the iframe approach earlier, I've changed my mind :-). Iframes can be nice if the code base is settled and there's no rush, but I believe we find ourselves in a different situation at the moment.

@spwoodcock
Copy link
Member Author

Sounds like a plan!

We should build upon the Web Component wrapper that ODK worked on (linked above) if possible, else failing that implement our own.

I still bet that bundling both Svelte and Vue (for now) will give an equivalent or smaller bundle size than React 😂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort:high Broader scope task with unclear timeline (consider splitting) enhancement New feature or request frontend Related to frontend code priority:high Should be addressed as a priority
Projects
Development

No branches or pull requests

2 participants