-1

I'm trying to use page-specific module with inline script but getting an error.

At first I have created a module and stored it in assets/js/tags.js

class TaggedImage {
    constructor(image) {
        this.image = image
    }
    ...
}
export {TaggedImage}

Then I added this module in webpack.config.js to specific route:

Encore
    ...
    .addEntry('photo_page', './assets/js/tags.js')

Now I'm trying to use this module with inline script in twig template:

<script>
    const myImage = new TaggedImage(document.getElementById('photoImage'));
    const tags = [
            {x:0.5, y:0.5, width:0.15, height:0.22},
            {x:0.65, y:0.33, width:0.13, height:0.19},
            {x:0.1222, y:0.398, width:0.10, height:0.335}
        ];
    myImage.addTags(tags).render();
</script>

Then I ran npm run dev in the terminal and it finished without errors.

...and after refreshing the page I get an error in the console:

Uncaught ReferenceError: TaggedImage is not defined

I noticed that my code is added to /public/build/photo_page.js but I don't see any mention of this file in page source.

0

1 Answer 1

-1

There are two things to your problem. The first one is that besides defining the entry in webpack.config, you have to explicitly import your javascript in your html.

You can do that with the twig helper function encore_entry_script_tags as described in the page specific scripts section of the manual.

So you would add:

{{ encore_entry_script_tags('photo_page') }}
<script>
// Here goes your script
</script>

Or override your block, if you have one, and call {{ parent() }} to include any additional scripts you require in all pages. Note that the entry tag will add the defer attribute by default, as configured in config/packages/webpack_encore.yaml, so you'll need to take that into account and wrap your script to fire on the load event.

The second one is that webpack doesn't expose modules to the global namespace. For that you would have to do it explicitly in your module:

// Instead of exporting the module, you export it to the global scope
// (the browser window in this case)
global.TaggedImage = TaggedImage;
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! Worked like a charm. Also I had to wrap my inline code into window.onload = function() { ... }
@NikitaBulatenko yes, that's because encore_entry_script_tags adds the attribute defer by default. This is controlled by the config/packages/webpack_encore.yaml configuration file.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.