AngularJS: Script tag not working in ng-include - angularjs

I have a file index.html with the following code:
<div ng-include="'fragment-1.html'"></div>
The code of fragment-1.html:
<b>Inside Fragment 1</b>
<script type="text/javascript">
alert("Inside Fragment 1");
</script>
When I load index.html into the browser, output is:
Inside Fragment 1
The DOM has the <script> tags but the alert is not shown.
My hypothesis:
Because the DOM loads first along with the Angular modules and then Angular checks and binds the data(in this case, fragment-1.html file content) to the view(index.html), it just adds the elements of fragment-1.html in DOM. To execute the JS inside fragment-1.html, we should create a hack for it. Am I right in this explanation? Or is there something else that I may be missing?

I had to load jQuery before loading Angular. The explanation is in the link specified above. Explanation: script not running in templateurl
To include another partial HTML file in your parent HTML file, one can also use Angular directives, depending on the situation. See this answer for when to use ng-include and when to use directives: https://stackoverflow.com/a/24172025/3132646

You don't need to hack. Angular gives you a neat and simple solution to what you want to achieve with your code.
Controller
.controller('fragmentOneCtrl', function ($scope) {
alert('"Inside Fragment 1"');
})
View
<div ng-repeat="go in ['go', 'gogo']" ng-include="'includeThis'">
</div>
<script type="text/ng-template" id="includeThis">
<div ng-controller="fragmentOneCtrl">
</div>
</script>

You may want to use $sce.trustAsHtml before injecting the resource in html

Related

script tag breaks sightly data-sly tag in author mode

I am using angular with sightly. So I have angular html template surrounded by script tag, which also has sightly attributes like data-sly-resource.
Below example code will give you clear idea.
<script type="text/ng-template" id="example.html">
<section data-sly-resource="${ #path='textOverImage', resourceType='example/components/textOverImage'}" id="textOverImage" >
<div ng-include="'private/textOverImage.html'" data-sly-test="${!wcmmode.edit}"></div>
</section>
</script>
It works fine in non-edit mode , but in edit mode, I can not author data-sly-resource part. It looks like <script> tag is not letting it work roperly because when I remove <script> tag ,than I can author it.
And removing script tag is not an option as well.
So how can I stop script tag form breaking sightly functionality in edit mode?
I ended up doing repetition of code , one for author mode and other for non edit mode.
Below is close resemblance of my solution.
<section data-sly-resource="${ #path='textOverImage', resourceType='example/components/textOverImage'}" id="textOverImage" data-sly-test="${wcmmode.edit}" >
<div ng-include="'private/textOverImage.html'"></div>
</section>
<script type="text/ng-template" id="example.html" data-sly-test="${!wcmmode.edit}">
<section data-sly-resource="${ #path='textOverImage', resourceType='example/components/textOverImage'}" id="textOverImage" >
<div ng-include="'private/textOverImage.html'"></div>
</section>
</script>
As you can see in above code, what to show and when works via data-sly-test="${wcmmode.edit}".
I also tried to to create sightly template for redundant code and than try data-sly-use but now, it works in author mode but sightly can't put template inside <script> tag even though I used # context='unsafe'
There is a workaround based on the Sightly Reference
Put the markup inside a separate html file say mymarkup.html parallel to mycomponent.html
In Component HTML file (e.g mycomponent.html) use <script type="text/ng-template" data-sly-include="mymarkup.html"></script>
In mymarkup.html we can use Sightly tags normally and those would be evaluated/executed normally, we would not even need to specify the # context for variables we would read using use API. The final markup rendered by component mycomponent.html when dragged to page would render something like this below
<script type="text/ng-template">
//mymarkup.html evaluated content here
</script>
In your script tag you could add data-sly-unwrap="${wcmmode.edit}"
This will remove script tag in edit mode allowing you to edit included components but in any other mode the script tag gets rendered.
I found the following mention in Netcentric's AEM Sightly Style Guide:
Then, because the HTML grammar ignores elements located inside a
< script > or < style > elements, no block statement can be used within
them.
Although it's not explicitly stated in the Sightly spec, it makes sense. So your fix is right.

Angular with Play (Scala): ng-include references

Situation
I started an app with Playframework (Scala) and AngularJS v1.3.
(Exactly the template Play Silhouette Angular Seed)
Goal
Loading difference templates using ng-include or a directive.
Problem
Always that I put a reference in Angular code, it doesn't work.
Example:
<div ng-include="'/tpl.html'"></div>
<script type="text/ng-template" id="/tpl.html">
Content of the template.
</script>
Result: works!!
Now, if I put the template tpl.html in a file in the same directory:
<div ng-include="'tpl.html'"></div>
Result: Doesn't work!! (And in other directories, I tried all the possible routes...)
The same problem occurs in directives, if I put the template inside the directory it works well, but if I try to put in another file it doesn't work.
Question
I used Angular in other projects and never occurs something like this. I think that this happens because Scala (language of Playframework) needs to be compiled and the files .scala.html are converted in .html.
How can I create some templates .html and then with ng-include
put the correct reference?
The root directory is the same that index.htmlfile (path: ui/app).
If the file view1.html is in the path ui/app, the ng-include will be like this:
<div ng-include="'./view1.html'"></div>
Because ui/app is the root path.

How can I display HTML in a <div> with Angular 1.2.0 - rc2

I am trying to display some HTML in my web page and using the following:
xx {{ pageHtml }} yy
<div data-ng-bind-html-unsafe="$scope.pageHtml"></div>
The data between xx and yy shows up as raw HTML but what I want is to not show it as raw. I used the code on the second line but nothing shows.
Is there something I am missing? Did something change in 1.2 because I thought this was working before?
Update - I do 100% trust the HTML and don't want to clean it. There will be code inside the HTML that needs to show on the screen.
By default the innerHTML-ed expression result is sanitized using the $sanitize service which would require you to include ngSanitize in your module's dependencies.
<div data-ng-bind-html="pageHtml"></div>
However if you trust the HTML to be safe, you can bypass sanitization using $sce service that you would inject in your controller:
$scope.someSafeContent = $sce.trustAsHtml("<i>Hello</i> <b>World!</b>");
HTML:
<!-- bypasses sanitizaton -->
<div data-ng-bind-html="someSafeContent"></div>
Controller
myApp.filter('unsafe', function($sce) { return $sce.trustAsHtml; });
In View
This will resolve your problem.

AngularJS - load dynamic template HTML within directive

I have a directive which loads content from an external HTML file. Passed into this directive is some scope data which is used in the rendering of that HTML fragment. e.g.
<div class="{{cls}}" data-obj="{{obj}}" data-id="{{id}}">
<!-- remainder of content here -->
</div>
What I would like to do within this directive is to load a further HTML partial within this based on the original scope data passed into the directive. I can't seem to get this to work, but it should be something along the lines of the following:
<div class="{{cls}}" data-obj="{{obj}}" data-id="{{id}}">
<!-- remainder of content here -->
<div ng-include="partials/{{obj}}.html></div>
</div>
Using this, the file doesn't get included, but I don't get any errors either. Can anybody assist me here?
NB: I read this, which is a similar issue, but hasn't helped me.
UPDATE - I noticed in Chrome dev tools that the URL is being resolved as expected, but the file contents are not getting included. I thought from the docs that ng-include loaded and compiled the requested fragment, so I was expecting this to work.
Found a solution in the end, by declaring the following in the directive:
<div ng-include src="view.getView()"></div>
and the following in the directive controller:
$scope.view = {
getView: function() {
return "partials/" + $scope.obj + ".html";
}
};
Works perfectly now!
In comment on the comment of Shane Gadsby: it is not <div ng-include src="'partials/'+{{obj}}+'.html'"></div> but <div ng-include src="'partials/'+obj+'.html'"></div>.
Your comment explains why 'this is what you need to force it from object literals to a string', so everything not in single quotes is handled by the compiler as a scope object.

Underscore templates with backbone boilerplate, correct way of doing it, or is there a better template method

Ok, I am playing around with Backbone, node.js, Underscore, Backbone Boilerplate so I have enough knowledge. Been asking questions like crazy as I still can't quite get my head around it. I am currently attempting to use the Underscore library with Backbone Boilerplate to make a very simple template which will allow me to pass in data; then when the model is updated, change the view which would change the template. I believe this is the correct way of doing it, instead of writing HTML code inside my JS file? Stop me if I'm wrong.
The Backbone Boilerplate has its template .fetch() system which I understand. However it would mean writing HTML in my JS I believe. So I wanted to use Underscore to simply pass information from the model to the view to the modules to render the template again (or I might be able to skip the view completely?).
My question is why won't this work, I think it's because I'm not changing it to JSON.
My HTML template:
<div>
<script id="rtemp" type="text/x-underscore-template">
<span><%= title %></span>
</script>​
</div>
And the JavaScript:
define([
// Global application context.
"app",
// Third-party libraries.
"backbone",
"underscore",
"json2"
],
function(app, Backbone) {
var Attempt = app.module();
Attempt.Model = Backbone.Model.extend({});
Attempt.Collection = Backbone.Model.extend({});
Attempt.Views.Tutorial = Backbone.View.extend ({
template: "app/templates/attempt",
render: function(done) {
var tmpl = app.fetchTemplate(this.template);
//console.info(tmpl);
this.$el.html(tmpl({title: 'This is a title'}))
}
});
return Attempt;
});
When I inspect the element it shows in the <div> however it still has the template script tags around it so doesn't show on the page in HTML. I tried using json2 to convert it to JSON first, but that didn't seem to work unless I did something wrong. Is Underscore the best thing to use? I assumed so as it's a Backbone dependency. Or should I use something else. I just want to avoid writing HTML in my JS.
If I understand you right, you're ending up with this HTML:
<div>
<script id="rtemp" type="text/x-underscore-template">
<span>This is a title</span>
</script>​
</div>
That's the right behavior based on the code you're using but that's clearly not the result you want.
The <script> wrapper for templates is used when you're embedding the template inside an HTML page. This is done so that the browser won't try to interpret your template as HTML and to keep the browser from trying to render it on its own. In such cases, you'd have the template embedded in the HTML page like this:
<!-- Some HTML stuff... -->
<script id="rtemp" type="text/x-underscore-template">
<span><%= title %></span>
</script>​
<!-- Some other HTML stuff... -->
and you'd use it like this:
var t = _.template($('#rtemp').html());
var html = t(...)
The $('#rtemp').html() part extracts just the content of the template's <script> wrapper so _.template would only see <span><%= title %></span> and the final processed template would just be a simple <span>. For example: http://jsfiddle.net/ambiguous/dzPzC/
In your case, you're reading the entire <div><script>...</script></div> as the template and feeding that to _.template. The result is that tmpl({title: 'This is a title'}) still includes the <script>, the browser doesn't know what to do with a <script type="text/x-underscore-template"> so the <span> that you're interested in doesn't get rendered at all.
You don't need the <script> wrapper at all, that's only needed when you're embedding a raw template inside some HTML. Your template only needs the the content of your <script>:
<span><%= title %></span>
Demo: http://jsfiddle.net/ambiguous/QuwSX/
The argument that you're passing to the template function:
tmpl({ title: '...' })
is fine, the compiled template function just wants to see a JavaScript object. People talk about passing it JSON and often use the toJSON method to prepare data for the template but that's an abuse of terminology; the template really wants an object and JSON is, technically, a string.

Resources