-
-
Notifications
You must be signed in to change notification settings - Fork 41
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
Forms support #27
Comments
Initial draftsLoading and saving entity data:Every form needs a load and a save declaration. Repository/Data model: <load method="\Magento\Customer\Api\CustomerRepositoryInterface::getById"
type="\Magento\Customer\Api\Data\CustomerInterface">
<bindArguments>
<argument name="customer_id" requestParam="id"/>
</bindArguments>
</load>
<save method="\Magento\Customer\Api\CustomerRepositoryInterface::save">
<bindArguments>
<argument name="customer" formData="true"/>
<argument name="passwordHash" method="\My\Module\Model\CustomerPassword::hash"/>
</bindArguments>
</save> ORM Model/Resource model: <load method="\Magento\Cms\Model\ResourceModel\Block::load" entity="\Magento\Cms\Model\Block">
<bindArguments>
<argument name="value" requestParam="id"/>
</bindArguments>
</load>
<save method="\Magento\Cms\Model\ResourceModel\Block::save"/> Not all of the elements and attributes above are required. When saving a form, the submitted data will be used to rehydrate an instance of form entity type, which will then be passed to the save method as the Form field declarationBy default, all fields with a getter and setter pair or, for EAV entities, all attributes, will be rendered as input fields. This default behavior can then be customized in similar way to grid columns. <fields>
<include keepAllSourceFields="true">
<field name="identifier"/>
<field name="title" template="My_Module::form/title-field.phtml" joinColumns="true"/>
<field name="content" type="wysiwyg"/>
<field name="creation_time" type="datetime"/>
<field name="is_active" type="boolean" sortOrder="10"/>
<field name="comment" enabled="false"/>
<field name="store_ids" type="select" source="\Magento\Eav\Model\Entity\Attribute\Source\Store"/>
<field name="admin" valueProcessor="\My\Module\Form\AdminLinkProcessor"/>
</include>
<exclude>
<field name="updated_at"/>
</exclude>
</fields> |
Field type determinationThe type determination will probably not be very reliable. Text input fields will be used as a lowest common denominator if no more specific input type can be automatically determined. Non-scalar values can be handled with a |
there's also use-case for hidden fields, field comments, field grouping , separators , labels , radio-buttons , submit button labels , submit button actions , ease of providing css, js inclusion paths per form |
@speedupmate can you give a little more info on what you would like to have for "js inclusion paths per form"? |
The sections in magento2 admin are under single layout handler, I'm not sure how you are approaching this but giving each form or section its in a separate layout handler would allow those forms to be targeted with css and js bit more elegantly |
@speedupmate Thanks for clarifying. Hyva Admin forms will be loaded using layout XML (or as a block in a |
|
Data FlowData needs to flow from the server into the rendered form, and then back again to the server. Loading data into the formSteps to determine the data shape for rendering the form:
Note: different from Hyvä grids, no type information is taken form the loaded data to build the form, only type reflection on the load method and the entity (if present) will be used together with the configured fields. Saving data from a form
Specific exceptions are used to communicate validation errors. |
I'm not so experienced with alpinejs jet but I think it is enough to leave your objects as x-data="{}" and provide all bindings to events in js implementation , you know like oldschool code and template separation. Otherwise its just like knockoutjs experience with bindings just all over the templates and a nightmare to debug Since you are defining forms the onsubmit and other event handlers you plan could be implemented/suggested as interface for js implementation to follow (simply put, to implement it you need certain set of methods) ? And def require js loaded from external file then it can be more easily debugged with developer tools. Adding to templates is easy and all but m2 is still a large project and diff teams need to provide diff features will end up with mixed practices and at some point the experience is not so cool any more. |
Sectioning and GroupingCurrently I think I'll use a similar strategy as is used in the system configuration. Fist draft of how it could work: <sections>
<section id="foo" label="Foos" sortOrder="10">
<group id="important-things" sortOrder="10"/>
<group id="details" sortOrder="20" label="Details"/>
</section>
<section id="bar" label="Bars" sortOrder="20">
<group id="whatever" sortOrder="10"/>
</section>
</sections>
<fields>
<include keepAllSourceFields="true">
<field name="identifier" group="important-things"/>
<field name="title" template="My_Module::form/title-field.phtml" group="important-things"/>
<field name="content" type="wysiwyg" group="details"/>
<field name="creation_time" type="datetime" group="whatever"/>
<field name="is_active" type="boolean" group="non-existent"/>
<field name="comment" enabled="false"/>
</include>
</fields> For EAV entities, fields can be automatically assigned to groups based on the The following scenarios have to be handled:
Given the above example, the fields would end up in the following hierarchy:
EDIT: replaced EDIT 2: <sections>
<section id="foo">
<group id="group1"/>
</section>
<section id="bar">
<group id="group1"/>
</section>
</sections>
<fields>
<include>
<field name="field1" group="group1"/>
</include>
</fields> Should this field be associated with
I think the only sane way to handle this is to throw an exception. Assigning fields to the first or last group with a matching ID would cause surprising and unwanted behavior, that is, fields suddenly moving to another section when a new group is declared. |
JS IntegrationMy current plan is to allow adding events to fields: <field name="title">
<event on="change"/>
<event on="keydown"/>
</field> The event name would be built from using the schema Subscribers receive an object containing the field element and the alpinejs view model along the lines of: this.$dispatch(event, {field: e.target, viewModel: this}); Forms always dispatches a Getting the subscribers onto the page is not the responsibility of the form. They can be added using layout XML. |
ButtonsBy default a form will have a single "Save" button, which posts the form to the build in save controller action. First draft: <navigation>
<buttons>
<button id="save" label="Save" url="hyva_admin/form/save" enabled="false" />
<button id="only-visible-when-entity-was-loaded" label="Example" hiddenForNewEntity="true"/>
<button id="reset" label="Reset" url="*/*/*"/>
<button id="validate">
<event on="click"/>
</button>
</buttons>
</navigation> (The JS integration would be whatever comes out of the discussion and prototyping related to issue #35.) If the label is omitted, the Any comments and thoughts are welcome as always. |
Entity RelationsOne of the most tricky things to model in regards to the forms are entity relations. Relations could be handled through embedded grids, multiselects, and so on. I don't think there is a one-size-fits-all solution. Over time I hope that Hyva_Admin forms will offer a couple of options to model relations in a form. However, in the first prototype release, I will intentionally not implement support for relations. Once the forms architecture settles a bit, then it will be time to revisit entity relation support. |
it's been a while, any updates on the progress? |
Hey @rbouma, thanks for asking! |
This is a high level issue for documenting design decisions in regards to form support in Hyva_Admin.
Design goals:
The most complex use cases always can be solved with custom form implementations.
Hopefully some of the code and thought that went into the grid design can be reused for forms.
The text was updated successfully, but these errors were encountered: