Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Implementing the Page Builder Preview (Template) Correctly

Implementing the Page Builder Preview (Template) Correctly

~6 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026

content_type.xml from chapter 59 already points at preview_component: Mironsoft_Loyalty/js/content-type/points-banner/preview - this chapter builds it.

Why a dedicated preview component is needed

Live editing means: on EVERY keystroke in the properties panel, the stage must immediately look different - with no server round trip per keystroke. A server round trip happens only once, when the master format is actually frozen (chapters 58/59). In between, a lightweight, purely client-side knockout component takes over, mirroring the same attribute names as the PHP template: heading, body_text, cta_label, cta_url, background_color.

app/code/Mironsoft/Loyalty/view/adminhtml/web/js/content-type/points-banner/preview.js
define([
    'jquery',
    'Magento_PageBuilder/js/content-type/preview',
], function ($, Preview) {
    'use strict';

    /**
     * Live-preview component for the "Points Banner" content type. Mirrors
     * Block/PageBuilder/PointsBanner.php's defaults (chapter 59) so the WYSIWYG canvas never
     * shows a value the frontend template wouldn't also show.
     */
    return Preview.extend({
        defaults: {
            template: 'Mironsoft_Loyalty/content-type/points-banner/preview',
        },

        /**
         * Returns the heading, falling back to the same default text as the PHP block.
         *
         * @returns {String}
         */
        heading: function () {
            var value = this.dataStore.get('heading');

            return value ? value : $.mage.__('Earn points on every order');
        },
    });
});
app/code/Mironsoft/Loyalty/view/adminhtml/web/template/content-type/points-banner/preview.html
<div class="pagebuilder-points-banner"
     data-bind="style: { backgroundColor: data.background_color() || '#0f172a' }">
    <h2 data-bind="text: heading()"></h2>
    <!-- ko if: data.body_text() -->
    <p data-bind="text: data.body_text"></p>
    <!-- /ko -->
    <!-- ko if: data.cta_label() -->
    <span class="pagebuilder-points-banner-cta" data-bind="text: data.cta_label"></span>
    <!-- /ko -->
</div>

One deliberate difference: the call-to-action

Achtung: The call-to-action button is deliberately a <span> in the preview, not a real <a href> like in the frontend template from chapter 59: a real link would navigate straight out of Page Builder the moment it's clicked while editing. The preview and the frontend template are allowed - even required - to diverge on exactly this one interactive detail, otherwise editors couldn't safely click near the button while composing the page.

Achtung: preview.html and default.phtml are two independently maintained files with no shared source of truth - the classic Page Builder maintenance trap. If a future change updates the default background color in PointsBanner::getBackgroundColor() but forgets the JS default in preview.js, the WYSIWYG stage silently lies about the actual result. Recommendation: after every change to either file, check the Page Builder editor AND the live storefront page side by side before merging.

Tipp: preview.js and preview.html use Knockout.js - and that's completely fine. CLAUDE.md's "no Knockout.js" rule applies to the Hyvä storefront theme, not to view/adminhtml assets: the Magento admin has been built on Knockout.js and UI components consistently since version 2.0, entirely independent of the Hyvä theme swap on the frontend. Nothing here violates the project convention.

Testing the preview

New files under view/adminhtml/web/ need a static content deploy run that also covers the admin area - unlike a pure layout XML change (chapter 51), a plain bin/cache-clean layout isn't enough here:

cd src && rm -rf var/view_preprocessed/* pub/static/frontend/* pub/static/adminhtml/*
bin/magento setup:static-content:deploy de_DE -f
bin/cache-clean config block_html full_page

Without a -t/--area restriction, this command deploys both affected areas - the frontend template from chapter 59 AND this chapter's new admin JS/knockout files - in a single step.