When you want to render HTML in AngularJS templates, you have to use the attribute ng-bind-html
. For security reasons, AngularJS requires you to add as dependency angular-sanitize
.
Below you can find an example on how to render HTML in the search results page.
Problem
You encounter the error Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context
when rendering HTML tags in an Angular JS template.
Example:
<div ng-repeat="record in vm.invenioSearchResults.hits.hits track by $index">
<div ng-bind-html="'<p>This is <em>HTML</em></p>'"></div>
<div class="well">
<h4>{{ record.metadata.abstract }}</h4>
</div>
</div>
Solution
Use angular-sanitize
. This example will refer to a new Invenio 3.2 installation, with site name my_site
.
-
Create a new JavaScript file
my_site/theme/assets/js/my_site/custom-search-app.js
to override the default AngularJS app ofinvenio-search-js
and injectngSanitize
:import angular from "angular"; import ngSanitize from 'angular-sanitize'; import "invenio-search-js/dist/invenio-search-js"; angular.element(document).ready(function () { angular.bootstrap(document.getElementById("invenio-search-custom"), [ "invenioSearch", "ngSanitize" ]); });
Take note of the
id
that you have used here (invenio-search-custom
), you will need it later. -
Add the new JS file and
angular-sanitize
to yourmy_site/theme/webpack.py
ormy_site/theme/bundle.py
. Don’t forget it to update the Python entry points in thesetup.py
if this is a new file.from flask_webpackext import WebpackBundle theme = WebpackBundle( __name__, 'assets', entry={ 'custom-theme': './scss/custom/theme.scss', 'custom-search-app': './js/custom-search-app.js', }, dependencies={ # add any additional npm dependencies here... 'angular-sanitize': '~1.4.9', } )
-
Override the default
search.html
template ininvenio-search-ui
. You will have to create a new file, e.g.my_site/theme/templates/my_site/search_custom.html
and copy/paste the content of the search.html file. Then, just change the HTML tagid
attribute that contains the search AngularJS application:... search.html code ... {%- block body_inner %} <div id="invenio-search-custom"> <invenio-search search-endpoint="{{ config.SEARCH_UI_SEARCH_API }}" search-extra-params='{% if search_extra_params %}{{search_extra_params|tojson}}{% endif %}' search-hidden-params='{% if search_hidden_params %}{{search_hidden_params|tojson}}{% endif %}' search-headers='{"Accept": "{{ config.SEARCH_UI_SEARCH_MIMETYPE|default('application/json')}}"}' > {{super()}} </invenio-search> </div> {%- endblock body_inner %} ... search.html code ...
-
Change your main config
my_site/config.py
to use this new template:SEARCH_UI_SEARCH_TEMPLATE = "my_site/search_custom.html"
-
Run the build again and restart the server:
./script/bootstrap ./script/server
or
pipenv run invenio collect -v pipenv run invenio webpack buildall ./script/server
or for older Invenio
(myvirtualenv) invenio collect -v (myvirtualenv) invenio assets build ./script/server