-
Notifications
You must be signed in to change notification settings - Fork 11
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
Revert select value type support #277
base: main
Are you sure you want to change the base?
Conversation
This is an engine-internal reorganization to improve some less-than-ideal naming and code structure around parsing selects, and helping to prepare for support of `<odk:rank>`. - Addresses a naming conflict between `SelectDefinition` (as a subtype of `NodeDefinition`) and `SelectDefinition` (as a parsed representation of `<select>` and `<select1>` **body elements**). The parsed body element is now named `SelectControlDefinition`. This naming is still not ideal! But it is consistent with the conceptual equivalents for other controls. - Anticipates similar parsing for `<odk:rank>` body elements. This may be easy to miss in review without calling it out, as it’s a change in file system structure. Specifically, each of the following are no longer structured as select-specific: - `ItemDefinition` - `ItemsetDefinition` This helps to prepare for `<odk:rank>` because it’s expected that both will be associated with a `RankControlDefinition`, providing the same parsed information about the control’s items to an implementation of `RankNode`/`RankControl`. - Removes `ItemsetNodesetContext`, which is evidently not in use at all!
Support for non-string bind/value types was introduced in #273. That support exceeds the current ODK XForms spec, which specifies both controls as supporting only a string type. We initially decided to merge that expansion on these bases: - XLSForms/pyxform do not produce forms with non-string select types, so it would only occur for forms authored as XML XForms, and would presumably be an intentional form design decision - The behavior (tested with `<select1>` + `<bind type=“int”>`) is consistent with Collect/JavaRosa We have since decided to revert that for now, because it would violate assumptions about _multiple values_ (from a `<select>`, and soon from `<odk:rank>`) associated with a non-string `<bind type>`. For example, this would break downstream projects which derive database schema types (e.g. SQL column types) from a form definition’s `<bind type>`.
🦋 Changeset detectedLatest commit: 0a6010e The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Would’ve been good to include this in #273.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like what I expect from a pretty quick pass through!
@@ -48,7 +48,7 @@ const BodyElementDefinitionConstructors = [ | |||
PresentationGroupDefinition, | |||
StructuralGroupDefinition, | |||
InputControlDefinition, | |||
SelectDefinition, | |||
SelectControlDefinition, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this will expand to something like ItemBasedControlDefinition
with the addition of rank
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see that becoming an abstract base class for select/select1/rank. Both concrete classes would still be enumerated here though, as it's used for instantiation during parsing. And the base class would make even more sense when we split select/select1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for sending this so fast!
I made a couple of suggestions, but it's mainly questions.
Let me know what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Questions:
The documentation of the scenario
package says:
This package implements a client of @getodk/xforms-engine, and a suite of tests and benchmarks against that engine.
-
When it says
... implements a client...
, is it a client to perform tests based on JavaRosa? Asking because when looking at the xforms-engine, there is already a client directory, and I was wondering about the difference. -
... and benchmarks against that engine.
, is it referring to performance tests? And, is there a baseline performance for what "good" means?
If I recall correctly, there was a delay when having groups and repeats simultaneously, which we'd like not to make it slower in Web Forms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion:
I understand the intent behind prioritizing reusability, but I'm considering ways to reduce the spread of what defines "select" to make it more self-contained as a component. Additionally, I suggest inverting the responsibility for the ID format.
Assuming the ID format is tied to the select functionality in the engine, what about moving the selectOptionId(...)
logic into the Select1Component
? Then, you could pass the formatter as an Input to the RadioButton
and CheckboxWidget
components.
This approach shifts the responsibility for defining the ID to the component that uses RadioButton
and CheckboxWidget
, which would provide greater flexibility. For example, if these components are later used in contexts requiring a different ID format, the adjustment would be simpler and more modular.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
Is the hierarchy defined based on the XML output?
For instance, are group
and repeat
considered higher-order components, while select
functions as a child or leaf in the tree? Additionally, should all new components be declared in this file first to ensure they are correctly mapped in the typing?
It seems like a good place to start for a new contributor to understanding the engine.
const { valueType } = definition; | ||
|
||
super( | ||
`Selects of type ${valueType} are not currently supported. If this functionality would be useful for your form, your feedback is welcome!` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion:
This seems like a common type of error for other components. What do you think about using generics in the declaration? Then, in the select definition (SelectNode? or SelectControl?), we could define the error type, extend it, and pass the types through the generic.
By centralizing the possible errors for select
within select definition (SelectNode? or SelectControl?), it would make them easier to discover and help provide a clearer picture of the entire select functionality.
@@ -0,0 +1 @@ | |||
export abstract class XFormsSpecViolationError extends Error {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
I like reusable errors in this folder!
What is this class for? What will it do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
- When codec run? I'm looking to know how to verify the output is what we expect
- I wonder if the Rank codec will be the same as this one and if we can reuse or duplicate it.
2.1 To reduce dependency between components, I would make 1 independent codec for Rank, but I want to know based on your experience with xforms
@@ -3,7 +3,7 @@ import type { | |||
KnownAttributeLocalNamedElement, | |||
LocalNamedElement, | |||
} from '@getodk/common/types/dom.ts'; | |||
import type { SelectElement } from '../../parse/body/control/select/SelectDefinition'; | |||
import type { SelectElement } from '../../parse/body/control/SelectControlDefinition.ts'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
Why do we have one for Select, while not for Range, Note, Inputs?
Looking to understand the reason so I can see if I need it for Rank or Geopoint
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Questions:
I didn't find Range in the reactivity
directory; maybe I missed it.
Why don't we have it but have it for Select?
What is the responsibility of reactivity
?
@@ -13,7 +14,7 @@ export class ItemDefinition extends BodyElementDefinition<'item'> { | |||
|
|||
constructor( | |||
form: XFormDefinition, | |||
override readonly parent: AnySelectDefinition, | |||
override readonly parent: AnySelectControlDefinition, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
I'm supposing that rank will use this, too. Does it make sense?
override readonly parent: AnySelectControlDefinition | RankControlDefinition,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
Does body parsing happen after the engine's client? I mean, the entry point is client then body parsing runs
I have verified this PR works in these browsers (latest versions):
What else has been done to verify that this works as intended?
Since this rolls back functionality in #273, the tests added for that functionality have been removed. I think everything else is covered by existing tests and/or type checks.
Why is this the best possible solution? Were any other approaches considered?
This leaves most of the other substantive improvements from #273 intact. Any considerations there apply here.
How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?
This is technically a regression! As of #273, Web Forms behavior for
<select1>
with a non-string<bind type>
was consistent with Collect/JavaRosa (for the current set of supported bind/value types). But we've decided that is an unsupported use case for now, as it isn't possible to produce an affected form with XLSForm/pyxform.Do we need any specific form for testing your changes? If so, please attach one.
The fixture added in #273 now produces an error on load (which is now expected). The fixture added in this commit demonstrates correct support for spaces in
<select1>
values (which could have been added in that PR as well).What's changed
The primary purpose of this change is to revert support for non-
string
<bind type>
s associated with a<select>
or<select1>
control (introduced in #273). It also establishes the same precedent for<odk:rank>
. The bulk of this aspect of the change involves:ValueType
type parameterization associated withSelectNode
and its implementationSome of the breadcrumbs for that functionality are left intact, in
ValueArrayCodec
. There are other use cases where we'll benefit from being able to derive encoding/decoding of array items (e.g. "select from map", which was part of the motivation for typed select support in the first place).I also took this PR as an opportunity to address a gap in the preparation for
<odk:rank>
, which I had neglected to address in #273. Specifically, the PR's first commit makes some structural changes to prepare for parsing<odk:rank><item>
or<odk:rank><itemset>
.Lastly, since I was already looking in that area, I went ahead and took care of these maintenance chores:
SelectDefinition
class associated with the body element is now namedSelectControlDefinition
, consistent with other parsed representations of similar controls. This eliminates a naming conflict where we also have an interface namedSelectDefinition
representing theNodeDefinition
associated with that control. (We really should take a more holistic look at naming, especially in these earlier areas of the engine package. For now, this is a piecemeal change aiming for consistency with current thinking.)ItemsetNodesetContext
, which was unused, is removed.