How to compile ng-include html file in a variable - angularjs

i'm storing a html string in a scope object and want to pass it to a variable
$scope.template1 = "div ng-include="'/app.html'" </div>"
Then i want to pass this template1 to my bootstrap template option with the output of $scope.template1
tour.start{
template:$scope.template1// Here i'm looking the output with the content of app.html
}
How can i compile template1 and pass the output?

Simply use the $compile service:
$scope.template1 = $compile("div ng-include="'/app.html'" </div>")($scope);
This way, your template will contain your ng-include content
(remember to add $compile to your dependencies).
By the way, I recommend that you use $templateCache service to store your static content in javascript, in order to have a unique place (and optimized too!) to store your templates:
app.run(function($templateCache) {
$templateCache.put('app.html', '<span> app.html content </span>');
});
and your ng-include will find automagically your app.html template.
You should do this also for your template1 variable, and retrieve it in your JS by using:
$templateCache.get('template1.html')

Related

AngularJS compile html with directive and get output as string?

Is there a way from an AngularJS controller or service to "compile/interpolate/whatever" a small html template which comes with a directive, and get the very final HTML output as a string?
More in details, let's say my template is like this:
var html = '<span my-directive="myVariable"></span>', and my-directive is adding additional html while manipulating myVariable.
Now, I would like to compile that html $compile(html)({myVariable: myVariable}) (not sure if it is the right way) and finally having a full html as a string as final result:
<span my-directive="myVariable">
<span>additional content added by my amazing directive while manipulating myVariable</span>
</span>
Any idea how to achieve this? Any advise is highly appreciated.
Cheers :)
Yes, you can compile HTML with directive (and also provide parameters/variables to that directive) and finally get the rusult as a String
Firstly, let's take a look $compile documentation (Usage section)
We can see there that $compile argument is
Element or HTML string to compile into a template function.
in your case it is var html
and the returned value is
a link function which is used to bind template (a DOM element/tree) to a scope
$compile is returning a function that require scope as an argument
scope is an special object so your {myVariable: myVariable} is not valid, if you want to pass variable to compilation, you have to assign this variable to your current scope scope.myVariable = myVariable and this scope has to be provided as an argument to link function $compile(html)(scope)
Now we must check what is returned by link function:
Calling the linking function returns the element of the template
voila! - we have Element Object so we can get its outerHTML property and assign it to a variable
In Pradeep Plunker you can change
var str = '<div my-directive>Hello world</div>'
var com = $compile(str)(scope);
element.append(com);
to
var str = '<div my-directive>Hello world</div>'
var com = $compile(str)(scope);
console.log('outerHTML',com[0].outerHTML);
element.append(com[0].outerHTML);
to watch results in console :)
NOTE: directive compiled in Plunker is not parametrized by any variable but you can change it of course (just remember that all variables used in compiled directive template have to be assigned to scope you compile with)
$compile compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together.
If your requirement is to append a compiled directive into another directive you can do it inside link function.
var str = '<div my-directive>Hello world</div>'
var com = $compile(str)(scope);
element.append(com);
You can use $compile as shown in the above code inside link function.
Example provided at Plnkr Example.
You can use $sce for that:
$scope.variable = $sce.trustAsHtml(yourHtmlString);
And then in your html you need to use:
<div ng-bind-html="variable"></div>

Id taken as file path for the template passed into ngDialog.open()

I am using ngDialog.open() to open a dialog. I want to pass in the template id to the function like this:
ngDialog.open({template: 'templateid'});
However, from the Network history, I find it is trying to fetch the templateid as a file on server.
I feel the ngDialog.open() function's interface design is a little confusing: The value of template options parameter can be either inline immediate HTML, or the file path of an HTML file on server, or the id of a <script> element. How should I distinguish them?
Thanks!
There are 2 options, not 3: either the filename for the template, or the template as a string. To provide the template as a string you set plain: true in the options to open(), so otherwise it will be interpreted as a filename.
The third option -- selecting the template by id -- is actually using a filename that is in Angular's $templateCache. If the name you provide is not in $templateCache for some reason, then it will be requested from the server.
One way to add a template to $templateCache is to use a script tag like this (example from Angular docs):
<script type="text/ng-template" id="templateId.html">
<p>This is the content of the template</p>
</script>
The main caveat here is that this must be somewhere inside the element that you have ng-app on.
The $templateCache docs also note that you can add a template in code by injecting $templateCache and calling $templateCache.put() and get one by calling $templateCache.get() which could be useful in debugging your situation.

injecting html content in empty template

I retrieve the code of an HTML page from a server thanks to a rest service and I want integrate the html code into an empty template
.controller('TestController', ['$scope' ,'$rootScope' , '$sce' , function ($scope ,$rootScope,$sce) {
var restHtml =$rootScope.test; //contains <div>Test</div>
$scope.showHtml= $sce.trustAsHtml(restHtml );
}]);
The template
<div ng-bind-html="showHtml"></div> <!-- didn't work and i want a solution without integrate my html code into a existing div -->
Thank you
Ideally DOM manipulations should not happen in the controller, directives should be used for them.
To answer your question, you could compile the html into your tag. Get the html, find the element you want to insert the html in and use compile to do it. A good example of compile.

Directive's templateUrl referencing div instead of entire HTML

I've got a list of pop-ups/dialogs (enclosed in divs) that I want to place in a single HTML file and from there reference in different directives representing those pop-ups. As far as I know, AngularJS directive's templateUrl normally reference an HTML file. Is it possible to reference a single div within HTML for templateUrl? If it is, how to do it?
If your template fragments are small, you can reference them from within your JS by using the template: parameter instead of templateUrl:. However, in my projects, I reference all the template partials by templateUrl and use a grunt task to preload all the individual HTML files into one Javascript file that is then loaded by Angular into the template cache. You can read more about it here.
You can do the following:
Add the div's as a <script> and add the attributes type="text/ng-template" and id="", then when you set the templateUrl:, you pass the id from the script element.
Example:
HTML:
<script type="text/ng-template" id="template/awesomeDiv.html">
<div>
(...)
</div>
</script>
Directive:
templateUrl: 'template/awesomeDiv.html'
NOTE:
In order to use this, you need to have nested directives, so the parent directive includes your HTML with all divs, and the children uses the ng-template'd divs

Best way to modify html before binding to it in AngularJS directive

I'm writing an AngularJS app that gets a list of posts from a server, and then uses an ngRepeat and a custom post directive to output all the posts.
Part of the post object is a blob of html, which I currently add to the directive by first doing an $sce.trustAsHtml(blob), and then using the ng-bind-html directive and passing the trusted html blob to it. It works fine, but now I want to modify the html before adding it to the output. For instance, I want to find all link tags and add a target="_blank" to it. I also want to remove any content editable attributes from any element. etc.
What is the best way of doing this? I was thinking of just loading it up in a document fragment and then recursively iterating through all of the children doing what I need to do. But I assume there is a better AngularJS way to do this?
EDIT:
here is a codepen with an example of what I have:
http://codepen.io/niltz/pen/neqlC?editors=101
You can create a filter and pipe (|) your content through it. Something like:
<p ng-bind="myblob | myCleanupFilter">
Your myCleanupFilter would look something like this (not tested):
angular.module('myApp').filter('myCleanupFilter', function () {
return function cleanup (content) {
content.replace('......') // write your cleanup logic here...
};
});
If you want to add attributes that are themselves directives, then the best place to add them is in the compile function in a custom directive.
If they are just plain old attributes, then there's nothing wrong with hooking into DOM ready in your run block, and adding your attributes with jquery.
var app = app.module('app',[]);
app.run(function ($rootScope){
$(document).ready(function()
$rootScope.$apply(function(){
$('a').attr('title','cool');
});
})
});
If you want add the attributes after the compile phase but before the linking phase in the angular life cycle then a good place to do it is in the controller function for a directive that's placed on the body element.
<body ng-controller="bodyCtrl">
</body>
app.controller('bodyCtrl', function($element){
$('a', $element).attr('title','cool');
});
During the compile phase angular will walk the DOM tree, matching elements to directives, and transforming the HTML along the way. During the link phase, directives will typically set up watch handlers to update the view when the model changes. By placing a directive on the body element, it ensures that all directives have been compiled, but the linking phase hasn't started yet.

Resources