How to Embed Asynchronous Content with hinclude.jsΒΆ

Embedding controllers in templates is one of the ways to reuse contents across multiple templates. To further improve performance you can use the hinclude.js JavaScript library to embed controllers asynchronously.

First, include the hinclude.js library in your page linking to it from the template or adding it to your application JavaScript using Webpack Encore.

As the embedded content comes from another page (or controller for that matter), Symfony uses a version of the standard render() function to configure hinclude tags in templates:

1
2
{{ render_hinclude(controller('...')) }}
{{ render_hinclude(url('...')) }}

Note

When using the controller() function, you must also configure the fragments path option.

When JavaScript is disabled or it takes a long time to load you can display a default content rendering some template:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/framework.yaml
    framework:
        # ...
        fragments:
            hinclude_default_template: hinclude.html.twig
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <!-- ... -->
        <framework:config>
            <framework:fragments hinclude-default-template="hinclude.html.twig"/>
        </framework:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    // config/packages/framework.php
    $container->loadFromExtension('framework', [
        // ...
        'fragments' => [
            'hinclude_default_template' => 'hinclude.html.twig',
        ],
    ]);
    

You can define default templates per render() function (which will override any global default template that is defined):

1
2
3
{{ render_hinclude(controller('...'),  {
    default: 'default/content.html.twig'
}) }}

Or you can also specify a string to display as the default content:

1
{{ render_hinclude(controller('...'), {default: 'Loading...'}) }}