Skip to content

Using JavaScript and Vue Components in .phtml Templates

With MageObsidian Components, integrating JavaScript files and Vue components into .phtml templates is made simpler and more powerful through the MageObsidian\ModernFrontend\Block\Template class.

This enhanced block class provides methods to efficiently load, resolve, and render resources, maintaining consistency with the import conventions explained earlier. Importing Between Magento Modules


Why Use MageObsidian\ModernFrontend\Block\Template?

This block class extends Magento's Template class and introduces powerful new methods, including:

  • Dynamic resource resolution: Supports the same Vendor_Module:: notation for resolving file paths.
  • Simplified Vue integration: Dynamically renders Vue components with properties.
  • Streamlined library access: Easily include library files or generated assets via Vite.

Key Features

1. Resolving File Paths

Files can be resolved dynamically using the resolvePathByName() method. This method allows you to reference files with the Vendor_Module:: notation or directly from themes using Theme::.

Example:

1
2
3
4
5
6
7
8
// Resolve a JavaScript file
$fileUrl = $block->resolvePathByName('Vendor_Module::js/main');

// Resolve a Vue component
$componentPath = $block->resolvePathByName('Vendor_Module::components/NavBar');

// Resolve a file from the theme
$themeFile = $block->resolvePathByName('Theme::custom-component');


2. Rendering Vue Components

The renderVueComponent() method generates the necessary HTML and JavaScript to load and mount a Vue component dynamically.

Example: Rendering a Vue Component in a .phtml Template

1
2
3
4
5
6
7
<?= $block->renderVueComponent(
    'Vendor_Module::NavBar',
    [
        'title' => 'Welcome',
        'userId' => 123
    ]
) ?>

The above code generates:

  • A <div> with a unique ID to host the Vue component.
  • A <script> block to load the Vue library, import the component, and mount it dynamically.

Rendered Output:

<div id="vue-component-4b3403665fea6"></div>
<script type="module">
    import { createApp } from 'https://magento.test/static/version1733144244/frontend/Vendor/theme/en_US/generated/lib/vue.js';
    import Component from 'https://magento.test/static/version1733144244/frontend/Vendor/theme/en_US/generated/Vendor_Module/components/NavBar.js';

    try {
        createApp(Component, {"title":"Welcome","userId":123}).mount('#vue-component-4b3403665fea6');
    } catch (error) {
        console.error('Failed to mount Vue component:', error);
    }
</script>


3. Loading Library Files

The getViewLibFileUrl() method allows you to include library files conveniently. For example, you can load a specific library script:

Example:

<script type="module" src="<?= $block->getViewLibFileUrl('some-library') ?>"></script>

This ensures consistency with your Vite-based build process.


4. Vite-Generated Files

Use the getViteFileUrl() method to load files generated by Vite, such as entry scripts or assets.

Example:

<script type="module" src="<?= $block->getViteFileUrl('Vendor_Module::main') ?>"></script>


Full Example in a .phtml Template

Here’s a complete example demonstrating multiple use cases:

<?php
/** @var MageObsidian\ModernFrontend\Block\Template $block */
?>

<!-- Include a JavaScript library -->
<script type="module" src="<?= $block->getViewLibFileUrl('some-library') ?>"></script>

<!-- Load a Vite-generated entry file -->
<script type="module" src="<?= $block->getViteFileUrl('Vendor_Module::main') ?>"></script>

<!-- Render a Vue component dynamically -->
<?= $block->renderVueComponent('Vendor_Module::NavBar', ['title' => 'Welcome to ModernFrontend', 'theme' => 'dark']) ?>

<!-- Resolve a file from the theme -->
<script type="module" src="<?= $block->resolvePathByName('Theme::custom-script') ?>"></script>

Best Practices

  1. Avoid Hardcoding File Paths
    Do not hardcode file paths. Instead, use the block methods like resolvePathByName(), getViteFileUrl() or getViewLibFileUrl() for consistent file resolution.

  2. Pass Props to Vue Components
    When rendering Vue components, pass only the necessary data as props to keep your components flexible and reusable.

  3. Keep Templates Clean
    Use the block methods to encapsulate logic, keeping your .phtml templates focused on structure and presentation.


Benefits of Using This Approach

  1. Dynamic Resolution
    Files and components are resolved dynamically, respecting theme overrides.

  2. Consistency
    Maintains a consistent approach to file handling across JavaScript, Vue components, and templates.

  3. Future-Proof
    By leveraging Vite and a modern block class, your integration is optimized for scalability and performance.

  4. Ease of Use
    Simplifies the process of including scripts and components, reducing boilerplate and errors.


Next Steps

  • Learn more about overriding components and scripts in the Themes section.
  • Explore how to integrate advanced features like lazy loading and conditional imports.