Can I incorporate AngularJS into hugo templates?

I am trying to render a section page in hugo using Angular. Only a single div in my document requires angular so there is no overlapping need of Angular vs Hugo templates. I have tried 2 approaches:

Approach 1:

Using hugo templates as usual, and for the <div> containing the Angular app, I create a separate HTML file and read it into my template for rendering like:

{{ blah de blah hugo templates}}
<div>
    {{readFile PATH_TO_ANGULAR_TEMPLATE_FILE.html}}
</div>
{{some more hugo templates}}

However this just dumps the text of the template file into the page.

Approach 2:

I copy the entirety of the angular app (html + css + json + js) into the static/ANGULAR_SECTION folder. So when I go to MY_SITE/ANGULAR_SECTION the page shows up. There are two downsides:

  • hugo server only shows an empty page on that address. But running another server like (python -m http.server) shows the working angular app.
  • I cannot use hugo templates on that section, so site-wide changes have to be made manually.

Does anyone know of a way to make AngularJS and Hugo play nice?

Really good question, anyone? The moustaches tag are maybe conflicting, can you use html encoding to write the angular {{ }} inside your Hugo? so Hugo will not try to catch them?

Or can we configure Angular to use different tag then {{ }} ?

I think that the best solution will by to used different tag. Taken from here.

var myApp = angular.module('myApp', [], function($interpolateProvider) {
    $interpolateProvider.startSymbol('[[');
    $interpolateProvider.endSymbol(']]');
});

I built a pop-over email opt-in form and I put the angular app in /static/js. https://github.com/appernetic/hugo-bootstrap-premium/blob/master/static/js/popover/popover.js

I had problems passing url’s from the config files to the angular app.

This is from my README.md:

Popover e-mail subscription opt-in form

The popover e-mail opt-in form is a bootstrap modal (also commonly referred to as a light box). You can configure it in the config.toml settings file. It detects mobile devices and sets a cookie. It will use a large modal and large buttons for mobile devices. You can enable/disable it, configure delay, activate popover if mouse leave window, number of days to not show it to visitors that has not subscribed, show an image etc. It is perfect to use it with services such as Zapier in combination with Mailchimp. The form will POST the variables: Email as a string and Optin as a boolean to the URL of your choice. The variables is case sensitive.

Remember to change the cookie name in settings to a unique name if you use the popover, there is a very small possibility that a visitor from another website has a cookie set with the same name you have set.

The popover is built with:

Angular.js 1.4.9
angular-modal-service v0.6.8
isMobile.js v0.3.9
angular-storage
In static/js/popover/ you will find a minified and a un-minified version of popover.js.

Workarounds to bugs that are not solved

I couldn’t use uibModalInstance. Somehow dots is escaped in variables that are between script tags in Hugo compiled html files. So it was not possible to pass url’s from the config file to the angular app. Possible not tested workaround for uib modal is to use: {{ .Site.Params.popover.posturl | safeJS }}
I had to use angular-modal-service and couldn’t get animation to work. So therefore no animations!
I could only get $location.absLangURL() to work in Angular so I had to do my own function to make the modal to work in the preview (in Appernetic).
Bugs

If the POST url is wrong you will not get the error message in the popover. Instead you get a success message or only an error in the browser console such as: XMLHttpRequest cannot load https://zapier.com/hooks/. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://preview.appernetic.io’ is therefore not allowed access. The response had HTTP status code 404.
And yes, it works on GitHub Pages if you have the correct Zapier hook!

I was able to resolve my issue by modifying my first approach. Essentially hugo passes read text through its filters to sanitize it. But piping the readFile output through safeHTML puts the actual HTML in the page. Like so:

{{ blah de blah hugo templates}}
<div>
    {{readFile PATH_TO_ANGULAR_TEMPLATE_FILE.html | safeHTML}}
</div>
{{some more hugo templates}}