Magewire driven forms
You have complete freedom in deciding how to manage your forms. While utilizing Magewire is one option, you could alternatively opt for a more frontend-centric approach such as AlpineJS. Each method has its own advantages and disadvantages, and the ideal choice depends on the specific use case.
Why use it?
Magewire presents a technique that provides both backend and frontend developers a means to create dynamic forms run via the server by XHR requests. This enables direct data syncing to the server, either on field completion or full form submission. Magewire offers a wide range of features to accommodate various requirements. If you lean towards a server-driven approach, Magewire can be utilized, powering default forms such as shipping and billing forms out of the box.
Example scenario
Since version 1.1.13, a new Magewire component has been unveiled, offering extensibility when constructing your form object. This component serves as a robust abstraction, converting your form into a dynamic entity that can be augmented with modifiers. It comes equipped with numerous modification hooks, allowing for the integration of custom hooks as needed to meet specific requirements.
For more global details on constructing a form, please refer to the documentation available here
We'll analyze a minimized version of the Guest Details component that is available from version 1.1.12.
1. Constructing the form component
<?php
class GuestDetails extends \Hyva\Checkout\Magewire\Component\AbstractForm
{
public bool $customerExists = false;
public function boot(): void
{
parent::boot();
$email = $this->getForm()->getField(GuestDetailsForm::FIELD_EMAIL);
if ($email && $email->hasValue()) {
$this->handleCustomerExistence($email->getValue());
}
}
// Magewire magic property hook method for $this->data['email_address'].
public function updatedDataEmailAddress($value)
{
$this->handleCustomerExistence($value);
// Submit and save the email value using the forms Save Service.
$this->submit([GuestDetailsForm::FIELD_EMAIL => $value]);
return $value;
}
// Try and toggle the customer existence variable value to either true or false.
private function handleCustomerExistence(string $email): void
{
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
try {
$this->customerExists = !$this->accountManagement->isEmailAvailable($email);
} catch (LocalizedException $exception) {
$this->logger->critical(sprintf('Something went wrong while checking the availability of the email address %s', $email));
}
}
}
}
2. Apply modifications (optional)
Additionally, we have the option to extend the base form on various triggers including form:init
, form:build:magewire
,
and form:execute:submit:magewire
.
For readability purposes, the hook callback methods are omitted in this example.
These modifier hooks ensure the following requirements:
On form:init
:
- The email field has the
autocomplete
attribute set tooff
. - An advanced form validation rule
email
is set totrue
. - The password field, along with a comment, is created and added.
- The submit button element, along with a custom
Submit
label, is created and added.
On form:build:magewire
:
- Utilizing the extended AlpineJS component
initMagewireFormForGuestDetails($el, $wire)
via ax-data
attribute on the form. - Setting a
wire:loading.attr
attribute asdisabled
on each field. - Hiding both the submit element and password field if the customer email address is non-existent.
- Making the fields compatible with the Magewire component by setting a
wire:model.defer
attribute asdata.{field_id}
. - Binding a new
submit
value onto the Magewire$loader
property, displayingTrying to authenticate
when the button is clicked.
<?php
class WithAuthenticationModifier extends \Hyva\Checkout\Model\Form\EntityFormModifierInterface
{
public function construct(
private readonly \Hyva\Checkout\Model\ConfigData\HyvaThemes\SystemConfigGuestDetails $systemConfigGuestDetails
) {
//
}
public function apply(\Hyva\Checkout\Model\Form\EntityFormInterface $form): \Hyva\Checkout\Model\Form\EntityFormInterface
{
if (!$this->systemConfigGuestDetails->enableLogin()) {
return $form;
}
$form->registerModificationListener(
'includeAuthentication',
'form:init',
fn ($form) => $this->includeAuthentication($form)
);
$form->registerModificationListener(
'handleMagewireAuthenticationForm',
'form:build:magewire',
fn (\Hyva\Checkout\Model\Form\AbstractEntityForm $form, \Hyva\Checkout\Magewire\Checkout\GuestDetails $component)
=> $this->handleMagewireAuthenticationForm($form)
);
$form->registerModificationListener(
'handleMagewireAuthenticationVisibility',
'form:build:magewire',
fn (\Hyva\Checkout\Model\Form\AbstractEntityForm $form, \Hyva\Checkout\Magewire\Checkout\GuestDetails $component)
=> $this->handleMagewireAuthenticationVisibility($form, $component)
);
$form->registerModificationListener(
'handleAuthenticationSubmitAction',
'form:execute:submit:magewire',
fn (\Hyva\Checkout\Model\Form\AbstractEntityForm $form, \Hyva\Checkout\Magewire\Checkout\GuestDetails $component, $result, $data, $exception)
=> $this->handleAuthenticationSubmitAction($form, $component, $result, $data, $exception)
);
return $form;
}
}
For a comprehensive understanding of the callback methods, please refer to \Hyva\Checkout\Model\Form\EntityFormModifier\GuestDetailsForm\WithAuthenticationModifier
3. Assign the modifier to the form
<!-- File: etc/frontend/di.xml -->
<type name="Hyva\Checkout\Model\Form\EntityForm\GuestDetailsForm">
<arguments>
<argument name="entityFormModifiers" xsi:type="array">
<item name="with_authentication_feature" xsi:type="object">Hyva\Checkout\Model\Form\EntityFormModifier\GuestDetailsForm\WithAuthenticationModifier</item>
</argument>
</arguments>
</type>
4. Make the checkout aware of the component
<!-- File: view/frontend/layout/hyva_checkout_components.xml -->
<referenceBlock name="hyva.checkout.components">
<container name="checkout.guest-details.section">
<block name="checkout.guest-details"
template="Hyva_Checkout::magewire/component/form.phtml"
>
<arguments>
<!-- Transform the form into a Magewire driven form. -->
<argument name="magewire" xsi:type="object">
\Hyva\Checkout\Magewire\Checkout\GuestDetails
</argument>
</arguments>
</block>
</container>
</referenceBlock>
5. Inject the component into the checkout shipping step