Skip to content

Evaluation result types

Hyvä Checkout provides evaluation result types for messaging, validation, and JavaScript execution during navigation. These result types range from basic error messages to sophisticated combinations like injecting executable code into the navigation process. The API is designed to allow developers to create custom evaluation result types for unique requirements.

Batch

Available since Hyvä Checkout 1.1.13

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\Batch
  • Frontend processor: batch
  • Capabilities: N/A

A batch result contains multiple evaluation results, all processed on the frontend. Batches have no restriction on the number or types of results they can carry. They operate like arrays with functions to traverse, push, or merge new results. Using a batch result is advisable as it allows others to inject additional functionality if needed.

This example creates a batch containing both a warning message and a JavaScript window event, dispatched immediately.

Example batch with multiple result types
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        $batch = $resultFactory->createBatch(
            [
                $resultFactory->createErrorMessage()
                    ->withMessage('Something went wrong.')
                    ->asWarning(),
                $resultFactory->createEvent()
                    ->withCustomEvent('my-batch-event')
                    ->dispatch()
            ]
        );

        // Example on how to push additional result types.
        if (false === $component->getEvaluationResultBatch()->owns(fn ($value) => $value instanceof Redirect)) {
            $batch->clear()->push($resultFactory->createRedirect('https://hyva.io/hyva-checkout.html')
                ->withNotificationDialog()
                ->withNotificationMessage('You\'re being redirected to the Hyvä Checkout product page.')
                ->withTimeout(2500)
            );
        }

        return $batch;
    }
}
Desire seamless access to the result factory without the need for manual injection?

You can achieve this by accessing a batch result. Within the batch result, there's a method named getFactory(), which provides access to the factory instance for creating various other result types.

$batch->push(
    $batch->getFactory()
        ->createErrorMessage()
        ->withMessage('Something went wrong.')
)

Blocking

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\Blocking
  • Frontend processor: blocking
  • Capabilities: Details, Blocking, Dispatch

Use a blocking result to completely disable all primary navigation buttons, preventing navigation tasks and validations from being triggered. However, this can confuse users. Provide clear instructions explaining what actions they need to take before they can proceed with navigation or placing an order.

Use With Caution

Additional care must be taken when choosing to return a Blocking result as there is currently no automated mechanism by which to unblock the checkout. Unblocking can only be achieved by satisfying the criteria for the component's evaluateCompletion() function to return a Success result or by manually invoking the unblocking via the frontend API.

Consider the example of a payment method which returns a Blocking result until the customer has authorised their payment. Upon selecting that payment method, the checkout becomes blocked. If the customer is unable to authorise their payment for any reason, they are then unable to complete their purchase even if they are to select an alternative payment method due to this Blocking result not being unset.

To simplify your implementation, it is generally advised to avoid returning a Blocking result in favour of an ErrorMessage result instead. The effects of preventing the customer from progressing through the checkout and displaying an informative error message are maintained but without the need to conceive of every scenario where you will have to handle the manual unblocking of the checkout.

This example demonstrates a conditional blocking result that prevents navigation based on a boolean condition.

Example blocking result implementation
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        return true ? $resultFactory->createBlocking() : $resultFactory->createSuccess();
    }
}

Custom

Available since Hyvä Checkout 1.1.13

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\Custom
  • Frontend processor: N/A
  • Capabilities: Details, Blocking, Dispatch

If you exclusively have a frontend processor, use a custom result type. By default, a custom result type has all the capabilities for dispatching, blocking, and adding additional details.

This backend implementation creates a custom result type with details that will be processed by a frontend processor.

Backend: Creating a custom result with details
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        return $resultFactory->createCustom('foo')
            ->withDetails(['alert' => 'Something went wrong.']);
    }
}

Register the custom frontend processor after the evaluation API is initialized. The processor receives the custom details from the backend.

Frontend: Registering the custom processor
<script>
    // Ensure that the evaluation API is fully initialized.
    window.addEventListener('checkout:init:evaluation', () => {
        // Register evaluation processor "foo".
        hyvaCheckout.evaluation.registerProcessor('foo', (component, el, result) => {
            alert(result.arguments.details.alert);

            return result.result;
        });
    });
</script>

Register custom evaluation processors

To register a custom processor, you can add a .phtml file to the DOM via layout XML. Multiple designated locations are available to ensure the custom processor is positioned correctly depending on the required hyvaCheckout APIs.

The recommended practice is to inject your custom .phtml via layout handle hyva_checkout_index_index with a container preference of hyva.checkout.init-evaluation.after.

Each API has its own after container, ensuring custom code can be injected after its parent API.

For further information, please refer to view/frontend/layout/hyva_checkout_index_index.xml.

ErrorMessage

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\ErrorMessage
  • Frontend processor: message
  • Capabilities: Blocking, Messaging, Dispatch

Use an error message result directly or during component validation to display feedback to customers.

This example shows an error message with options to be dispatched immediately, displayed as a success message (despite the result type ErrorMessage), and with the option of setting a visibility duration.

Error message with customization options
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public bool $dispatch = false;
    public bool $successful = true;
    public ?int $duration = null;

    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        $message = $resultFactory->createErrorMessage('Something went wrong');

        if ($this->dispatch) {
            $message->dispatch();
        }
        if ($this->successful) {
            $message->asCustomType('success');
        }
        if ($this->duration) {
            $message->withVisibilityDuration($this->duration);
        }

        return $message;
    }
}

Event

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\Event
  • Frontend processor: event
  • Extends: ErrorMessageEvent, ErrorEvent, Success
  • Capabilities: Details, Dispatch

The Event result type functions as an event shell and extends ErrorMessageEvent and ErrorEvent, providing specific markup for error events and message events.

This example demonstrates three ways to create and dispatch custom events: a basic window event, an error message event with custom messaging, and an error event attached to the validation API.

Event result type variations
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        // Can be caught with window.addEventListener('my-custom-event', event => {})
        return $resultFactory->createEvent()
            ->withCustomEvent('my-custom-event')
            ->dispatch();

        // Dispatch a custom window event with a specific message markup containing the message and its type.
        return $resultFactory->createErrorMessageEvent()
            ->withCustomEvent('my-error-event')
            ->withMessage('Something went wrong')
            ->dispatch();

        // Dispatch a custom window event with a false result and stick it onto the validation API by default.
        return $resultFactory->createErrorEvent()
            ->withCustomEvent('my-custom-event');
    }
}

Executable

Available since Hyvä Checkout 1.1.13

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\Executable
  • Frontend processor: executable
  • Capabilities: Dispatch

Use an executable result, either combined with the NavigationTask result type or independently, when you need specific code executed on the frontend. An executable can be thought of as a regular method that receives its own argument parameters set from the backend.

This backend example creates an executable with parameters and shows two usage patterns: dispatching immediately or attaching to navigation.

Backend: Creating executable with parameters
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        $executable = $resultFactory->createExecutable('custom-modal')
            ->withParams(['buttons' => ['confirm', 'cancel']]);

        // Dispatch the executable immediately.
        return $executable->withParam('title' => 'My Modal');

        // Attach the executable to the navigation and trigger it only when a customer attempts to navigate.
        return $resultFactory->createNavigationTask('foo', $executable)
    }
}

Register the executable on the frontend after the evaluation API is initialized. The executable can function as asynchronous or synchronous. This example shows an async executable that opens a modal after 5 seconds.

Frontend: Registering an asynchronous executable
<script>
    // Ensure that the evaluation API is fully initialized.
    window.addEventListener('checkout:init:evaluation', () => {
        // Open a modal after 5 seconds, including fetched data from an external API.
        hyvaCheckout.evaluation.registerExecutable('custom-modal', async (result, el, component) => {
            return new Promise(resolve => setTimeout(() => {
                fetch('https://api.example.extension/random').then(result => {
                    // Custom logic to open a modal goes here.
                })

                resolve()
            }, 5000))
        })
    })
</script>

Available since Hyvä Checkout 1.1.13

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\NavigationTask
  • Frontend processor: navigation_task
  • Capabilities: Dispatch, Stacking

A navigation task delays specific JavaScript-driven actions until the customer chooses to advance to the next step or place an order. Tasks remain pending until the customer clicks the navigation button, executing sequentially based on their assigned position (default: 500).

Consider address form data that no other component depends on but still requires preservation. This approach negates the need for an auto-save feature, as the navigation mechanism handles data retention when necessary.

A navigation task can contain any type of evaluation result. If the result is dispatchable, it will be automatically handled. The task can also be assigned to execute after the successful loading of the next step or the completion of the order.

This example creates a success message that displays after the customer proceeds to the next step or places the order.

Navigation task executing after navigation
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        $task = $resultFactory->createErrorMessage()
            ->withMessage('Welcome to the next step.')
            ->asCustomType('success');

        // "fooCustomNavigationTask" will serve as the identifier for the navigation task on the frontend.
        return $resultFactory->createNavigationTask('fooCustomNavigationTask', $task)->executeAfter();
    }
}

This manifests as an error message displayed as a success-type flash message at the top of the screen. This occurs either after the customer proceeds to the second page or after placing the order, prior to any redirection. For example, you might display a modal through an asynchronous Executable, ensuring navigation waits until the modal is resolved. Since the Redirect result is positioned late in the task stack, it permits other tasks to execute beforehand.

Redirect

Available since Hyvä Checkout 1.1.13

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\Redirect
  • Frontend processor: redirect
  • Capabilities: Dispatch, Stacking

The redirect result type is particularly valuable for payment vendors, enabling redirection to external payment solutions before or immediately after order placement. This redirect functionality includes a modal that can appear as a notification dialog. Alternatively, developers can present a confirmation dialog to the customer with cancel and confirm buttons.

These options can be configured within the redirect system settings, allowing system administrators to enforce confirmation dialogs for all redirects, even if developers choose not to attach them initially.

This example creates a redirect attached to a navigation task that executes after the customer proceeds or places an order.

Redirect result with navigation task
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        $task = $resultFactory->createRedirect('https://hyva.io/hyva-checkout.html');

        return $resultFactory->createNavigationTask('foo', $task)->executeAfter();
    }
}

Custom Redirect Template

Available since Hyvä Checkout 1.3.4

Hyvä Checkout 1.3.4 introduced the ability to define a custom frontend template for the Redirect Result. This allows customization of the content displayed to customers during the redirect phase after placing an order, for example, displaying a branded loading screen or custom messaging.

This Place Order Service example creates a redirect with a custom template for the redirect screen.

Place Order Service with custom redirect template
<?php

class MyCustomPlaceOrderService extends \Hyva\Checkout\Model\Magewire\Payment\AbstractPlaceOrderService
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory, ?int $orderId = null): EvaluationResultInterface
    {
        return $resultFactory
            ->create(PlaceOrderRedirect::class, ['url' => 'https://hyva.io/hyva-checkout.html'])
            ->withRedirectTemplate('Hyva_Checkout::redirect-to-hyva.phtml');
    }
}

The template passed via withRedirectTemplate(string $template) can contain any custom HTML and styling.

view/frontend/templates/redirect-to-hyva.phtml
<div>
    Hello from the Hyvä checkout docs!
</div>

Since PlaceOrderRedirect extends Redirect, it remains fully compatible with the existing frontend processor and behaviors expected by the PlaceOrderProcessor. This ensures seamless integration with the checkout flow while providing additional customization opportunities for the post-order redirect experience.

Success

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\Success
  • Frontend processor: event
  • Capabilities: Details, Dispatch

Although Success is simply a standard Event result type, it holds significance as it is the primary type used for clearing a component and marking it as completed. In addition to dispatching a success result for the component (valuable on the frontend), it also returns a true result, indicating the component's completion status. Other result types, such as a custom one returning a true result, will also function effectively. However, this standardized type streamlines common functionalities.

This example marks a component as completed when a boolean property is true, otherwise displays an informational error message.

Success result with conditional completion
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public bool $success = true;

    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        if ($this->success) {
            return $resultFactory->createSuccess();
        }

        return $resultFactory->createErrorMessage()
            ->withMessage('Please mark this component as completed.')
            ->asInformally()
            ->dispatch()
    }
}

Validation

Available since Hyvä Checkout 1.1.13

  • Class: \Hyva\Checkout\Model\Magewire\Component\Evaluation\Validation
  • Frontend processor: validation
  • Capabilities: Stacking, Details

The validate result type is tightly integrated with the frontend Validation API, offering developers the flexibility to inject custom validation logic onto primary navigation buttons. This validation occurs after navigation tasks have been successfully fulfilled. A validation result behaves similarly to a NavigationTask, with the main distinction being that the registered callback serves as a validator. Developers can specify another result type, such as ErrorMessage, to handle failure scenarios automatically using the withFailureResult method.

This backend example creates a validation result that randomly selects one of three validators and attaches an error message to display if validation fails.

Backend: Validation with failure result
<?php

class Foo extends \Magewirephp\Magewire\Component implements \Hyva\Checkout\Model\Magewire\Component\EvaluationInterface
{
    public function evaluateCompletion(EvaluationResultFactory $resultFactory): EvaluationResult
    {
        // Reflects one of the tree register validators on the frontend.
        $validator = ['a', 'b', 'c'][random_int(0, 2)];

        return $resultFactory->createValidation($validator)
            ->withFailureResult($resultFactory->createErrorMessage()
                ->withMessage(sprintf('Validator "%s" failed.'))
                ->dispatch()
            );
    }
}

Register validators on the frontend after the evaluation API is initialized. Validators can be asynchronous or synchronous. This example shows three validators with different behaviors: immediate failure, async success, and async failure.

Frontend: Registering validators with different behaviors
<script>
    window.addEventListener('checkout:init:evaluation', () => {
        // Fails validation immediately.
        hyvaCheckout.evaluation.registerValidator('a', (element, component) => {
            throw new Error('Foo')
        })

        // Successful validation after 2.5 seconds.
        hyvaCheckout.evaluation.registerValidator('b', async (element, component) => {
            return new Promise(resolve => setTimeout(() => resolve(true), 2500))
        })

        // Rejects and fails validation after 2.5 seconds.
        hyvaCheckout.evaluation.registerValidator('c', async (element, component) => {
            return new Promise((resolve, reject) => setTimeout(() => reject(), 2500))
        })
    })
</script>

Register custom validator

To register a custom validator, you can add a .phtml file to the DOM via layout XML. Multiple designated locations are available to ensure the custom processor is positioned correctly depending on the required hyvaCheckout APIs.

The recommended practice is to inject your custom .phtml via layout handle hyva_checkout_index_index with a container preference of hyva.checkout.init-evaluation.after.

Each API has its own after container, ensuring custom code can be injected after its parent API.

For further information, please refer to view/frontend/layout/hyva_checkout_index_index.xml.

EvaluationResult (abstract)

Available since Hyvä Checkout 1.1.13

For checkout versions before 1.1.13, every evaluation result type mandates an implementation of Hyva\Checkout\Model\Magewire\Component\EvaluationResultInterface.

However, starting from version 1.1.13, this interface has been deprecated and replaced with \Hyva\Checkout\Model\Magewire\Component\Evaluation\EvaluationResult.

Every core evaluation result type builds upon the EvaluationResult abstraction, ensuring that all necessary requirements are fulfilled. The recommended approach is to extend custom results from this abstraction, adhering to best practices.

This example shows the basic structure for creating a custom evaluation result type by extending the EvaluationResult abstract class.

Custom evaluation result type structure
<?php

namespace My\Module\Model\Magewire\Component\Evaluation;

class Foo extends \Hyva\Checkout\Model\Magewire\Component\Evaluation\EvaluationResult
{
    public const TYPE = 'foo';

    public function getArguments(Component $component): array
    {
        return [];
    }

    // Alternative for defining a TYPE constant.
    public function getType(): string
    {
        return 'foo';
    }
}