Skip to content

Evaluation examples

The evaluation API serves a variety of purposes across different contexts, including the integration with both new and existing Magewire components.

Additionally, starting from version 1.1.13, it offers compatibility with existing or custom Place Order Services, which can be seamlessly integrated with payment methods as needed.

Browsing through the documentation will provide you with a basic understanding of its functionalities.

However, for a deeper comprehension, we've included a few examples to illustrate potential applications.

These examples will offer insight into the possibilities that can be achieved through its implementation.

New features since 1.1.13 will be marked.

Credit card authorization

In this case, a payment method necessitates extra authorization before proceeding to the next step or placing the order.

Custom validation will be triggered upfront, with a loading indicator displayed until completion.

If validation fails, an error message will appear within the component.

Alternatively, the customer will proceed to the next step or the order placement process will commence.

1. Create the component

In this case we're going to create a very straightforward Magewire component implementing the EvaluationInterface and have a single field that needs to be validated when hitting the primary navigation button.

<?php

use Magewirephp\Magewire\Component;
use Hyva\Checkout\Model\Magewire\Component\EvaluationInterface;
use Hyva\Checkout\Model\Magewire\Component\EvaluationResultFactory;
use Hyva\Checkout\Model\Magewire\Component\Evaluation\EvaluationResult;

class Cc extends Component implements EvaluationInterface
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        /*
         * Since 1.1.13
         * 
         * Direct the frontend to execute "validateMyCustomCcComponent" and
         * trigger an error message event in case of failure.
         */
        return $resultFactory->createValidation('validateMyCustomCcComponent')
            ->withFailureResult(
                $resultFactory->createErrorMessageEvent()
                    ->withCustomEvent('payment:method:error')
                    ->withMessage('Invalid credit card details provided. Please try again.')
                    ->withVisibilityDuration(5000)
             );

        /*
         * Before 1.1.13
         * 
         * Either need to provide a mock success result or not implement the EvaluationInterface.
         */
        return $resultFactory->createSuccess();
    }
}

2. Inject the component into the checkout

In this scenario, we assume that this pertains to a payment method requiring registration with an alias corresponding to the payment method code.

Further instructions on implementing a custom payment method can be found here.

As it is a payment method, the checkout framework will automatically search for a corresponding block and attempt to render its template as soon as it is found.

<!-- File: view/frontend/layout/hyva_checkout_components.xml -->
<referenceBlock name="hyva.checkout.components">
    <block
        name="checkout.payment.method.cc"
        as="cc"
        template="My_Example::checkout/payment/method/cc.phtml"
    >
        <arguments>
            <argument name="magewire" xsi:type="object">
                \My\Example\Magewire\Checkout\Payment\Method\Cc
            </argument>
        </arguments>
    </block>
</referenceBlock>

3. Create the frontend validation

Now we need to inject a custom validator.

While we could include it directly in the PHTML of the component, it's advisable to inject it into either the hyva.checkout.api-v1.after or hyva.checkout.init-evaluation.after containers for better organization and maintainability.

<script>
    /*
     * Since 1.1.13
     * 
     * We wait for the evaluation API to be initialized where after
     * we register a validator named "validateMyCustomCcComponent".
     */
    window.addEventListener('checkout:init:evaluation', event => {
        hyvaCheckout.evaluation.registerValidator('validateMyCustomCcComponent', (element, component) => {
            return Math.random() < 0.5 // Randomly return true of false.
        })
    })

    // Before 1.1.13
    window.addEventListener('checkout:init:validation', event => {
        hyvaCheckout.validation.register('validateMyCustomCcValidation', () => {
            const result = Math.random() < 0.5 // Randomly return true of false.

            if (result) {
                return true
            }

            // Dispatch a custom message to the payment method messenger block.
            hyvaCheckout.messenger.dispatch(
                'payment:method',
                'Invalid credit card details provided. Please try again.'
            )

            return false
        })
    })
</script>

Marketing Opt-In Example

Consider a case where the merchant is using a third-party marketing service and they want to allow customers to sign up to receive marketing communications as part of their checkout journey.

Because this registration is optional it would not make sense to use a Validation result, but rather an Executable result instead.

We can also combine this with a Navigation Task result to execute the registration logic after the customer successfully navigates to the next step of the checkout.

1. Create the Magewire Component

We can use a very simple Magewire component to track whether the customer has agreed to receive the marketing communications and implement the EvaluationInterface to create the Navigation Task.

Note the use of the withParam() function. This can be used to forward data to the frontend upon execution.

<?php

declare(strict_types=1);

namespace Vendor\Module\Magewire;

use Magewirephp\Magewire\Component;
use Hyva\Checkout\Model\Magewire\Component\EvaluationInterface;
use Hyva\Checkout\Model\Magewire\Component\EvaluationResultFactory;
use Hyva\Checkout\Model\Magewire\Component\EvaluationResultInterface;

class MarketingCheckbox extends Component implements EvaluationInterface
{
    public bool $shouldRegister = false;

    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResultInterface
    {
        $executable = $resultFactory
            ->createExecutable('marketingRegistrationExecutable')
            ->withParam('shouldRegister', $this->shouldRegister);

        return $resultFactory
            ->createNavigationTask('marketingRegistrationTask', $executable)
            ->executeAfter();
    }
}

2. Create the Checkbox Block

Use layout XML to add the new component to the desired location in the checkout using the hyva_checkout_components.xml layout handle. In this example we're going to simply append it to the summary block.

<?xml version="1.0"?>
<page
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"
>
    <body>
        <referenceContainer name="hyva.checkout.api-v1.after">
            <referenceContainer name="checkout.quote-summary.section">
                <block
                    name="marketing.checkbox.component"
                    template="Vendor_Module::checkbox.phtml"
                    after="-"
                >
                    <arguments>
                        <argument name="magewire" xsi:type="object">
                            Vendor\Module\Magewire\MarketingCheckbox
                        </argument>
                    </arguments>
                </block>
            </referenceContainer>
        </referenceContainer>
    </body>
</page>

3. Create the Checkbox Template

<?php

declare(strict_types=1);

use Magento\Framework\Escaper;
use Magento\Framework\View\Element\Template;
use Vendor\Module\Magewire\MarketingCheckbox;

/** @var Escaper $escaper */
/** @var Template $block */
/** @var MarketingCheckbox $magewire */
?>

<label>
    <input
        type="checkbox"
        name="checkbox_component"
        wire:model="shouldRegister"
    >
    <span><?= $escaper->escapeHtml(__(
        'Would you like to receive marketing emails from us? %1',
        $magewire->shouldRegister ? 'Yes' : 'No'
    )); ?></span>
</label>

4. Create the Navigation Task Block

Use layout XML to add the block containing the navigation task callback using the hyva_checkout_index_index.xml layout handle.

<?xml version="1.0"?>
<page
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"
>
    <body>
        <referenceContainer name="hyva.checkout.api-v1.after">
            <block
                name="marketing.checkbox.navigation.task"
                template="Vendor_Module::js/checkbox.phtml"
            />
        </referenceContainer>
    </body>
</page>

5. Create the Navigation Task Template

Listen for the checkout:init:evaluation event and use the hyvaCheckout.evaluation.registerExecutable() function, to register your executable callback with the frontend.

The first parameter to this function is the name of the executable, which MUST match the name given in the Magewire component, while the second parameter is the callback.

The callback has access to a result parameter where we can find the data forwarded by our Magewire component.

<?php
declare(strict_types=1);

use Magento\Framework\Escaper;
use Magento\Framework\View\Element\Template;

/** @var Escaper $escaper */
/** @var Template $block */
?>

<script>
    window.addEventListener('checkout:init:evaluation', event => {
        hyvaCheckout.evaluation.registerExecutable(
            'marketingRegistrationExecutable',
            (result, element, component) => {
                if (result.arguments.params.shouldRegister) {
                    // marketing registration logic
                }
            }
        );
    });
</script>

Notes

The Navigation Task callback will NOT execute after the initialization of the checkout, but WILL execute every time the customer navigates to or from the step that contains our MarketingCheckbox component.

Should this have been an implementation designed for an actual marketing integration, we would likely want some mechanism to flag when the API call has been successful.
So that we can avoid making duplicate requests.