angular load template from url and compile inside div - javascript

As I'm new to Angular JS I was wondering how could I load an external template and compile it with some data into the targeted div.
For instance I have this template :
<script type="text/ng-template">
<img src="{{Thumb}}" />
<script>
The div that is supposed to contain the template :
<div data-ng-controller=" ... "></div>
The template is located somewhere in a folder /templates/test.php. Is there a build in way of doing the template loading like a directive would do and compile it against some data that would replace the key {{Thumb}} ( and many others of course ) ?
EDIT : What if I use $routes and load a template when I'm in the root of the website ? How could that be achieved ?

Using $templateRequest, you can load a template by it’s URL without having to embed it into your HTML page. If the template is already loaded, it will be taken from the cache.
app.controller('testCtrl', function($scope, $templateRequest, $sce, $compile){
// Make sure that no bad URLs are fetched. If you have a static string like in this
// example, you might as well omit the $sce call.
var templateUrl = $sce.getTrustedResourceUrl('nameOfTemplate.html');
$templateRequest(templateUrl).then(function(template) {
// template is the HTML template as a string
// Let's put it into an HTML element and parse any directives and expressions
// in the code. (Note: This is just an example, modifying the DOM from within
// a controller is considered bad style.)
$compile($("#my-element").html(template).contents())($scope);
}, function() {
// An error has occurred here
});
});
Be aware that this is the manual way to do it, and whereas in most cases the preferable way would be to define a directive that fetches the template using the templateUrl property.

in Angular there's 2 ways of using template (at least 2 ways that i know about):
the first using an inline template (in the same file) with this syntax:
<script type="text/ng-template">
<img ng-src="{{thumb}}">
</script>
the second one (what you want) is external template:
<img ng-src="{{thumb}}">
so what you need to do is to remove the script part from your template and then use the ng-include in the wanted div like this:
<div ng-include="'templates/test.php'"></div>
need to have double quotes and single quotes to work.
Hope this helps.

Let's say I have this index.html:
<!doctype html> <html lang="en" ng-app="myApp">
<body>
<script src="tpl/ng.menu.tpl" type="text/ng-template"></script>
<mainmenu></mainmenu>
<script src="lib/angular/angular.js"></script>
<script src="js/directives.js"></script>
</body>
</html>
And I have a template file "tpl/ng.menu.tpl" with only these 4 lines:
<ul class="menu">
<li>view1</li>
<li>view2</li>
</ul>
My directives mapping "js/directives.js":
angular.module('myApp',['myApp.directives']);
var myModule = angular.module('myApp.directives', []);
myModule.directive('mainmenu', function() {
return {
restrict:'E',
replace:true,
templateUrl:'tpl/ng.menu.tpl'
}
});

Related

Directive for dynamically adding JavaScript files

Is it possible to use ng-repeat to dynamically add script files to my html file?
I have a directive like below:
angular.module("app").directive("scriptLoader", function($compile) {
return {
template: "<script ng-repeat='s in files' src={{s}}></script>",
scope: true
}
});
Meanwhile files is a scope variable in my controller:
$scope.files = ["test.js", "script.js"];
And I get the html rendered as:
<script-loader class="ng-scope">
<script ng-repeat="s in scripts" src="test.js" class="ng-scope"></script>
<script ng-repeat="s in scripts" src="script.js" class="ng-scope"></script>
</script-loader>
But it doesn't work since whenever I try to invoke a method from the loaded files, it just says the method is not defined.
I'm just curious why can't I load script like this. Please help!

Javascript ads in Angular templates

I'm trying to render a Javascript ad in my Angular template but it will not show up. I've found some solutions when they append the Javascript to the head tag but I want the ad to be placed in my Html (inside body).
Here is a Plunker: https://plnkr.co/edit/WHhQ95gS5HKSphmmirio
Here is a simple plain Html example that works.
<html>
<head>
</head>
<body>
<div class="ad">
<script src="http://media.affiliatelounge.com/data/nordicbet/ad_js/display_88.js?ad=ad_793270_88.html&size=300x250&clicktag=http://record.affiliatelounge.com/_sVuSoFFh4LK58VwA2IUESrKVVrME-Gsw/1&media=108786&campaign=1"></script>
</div>
</body>
</html>
But if I add the div inside an Angular template it will not render and the console says nothing.
I have some ads up and running here (http://www.odds.nu/erbjudanden), but they are either .gif or iframes. I want to be able to show Javascript ads instead. They are added to the Html but are not rendered (placed in the bottom of the page).
Can $sce or $compile help somehow?
My index.html
<div data-ng-view="" class="mainView"></div>
My app.js
$routeProvider.when("/erbjudanden", {
controller: "offerController",
templateUrl: "/app/templates/offers.html"
});
My offers.html
<div class="ad">
<script src="http://media.affiliatelounge.com/data/nordicbet/ad_js/display_88.js?ad=ad_793270_88.html&size=300x250&clicktag=http://record.affiliatelounge.com/_sVuSoFFh4LK58VwA2IUESrKVVrME-Gsw/1&media=108786&campaign=1"></script>
</div>
Any solution?
If you had inspected result of that url request(make sure adBlock is off)
https://wlbetclic.adsrv.eacdn.com/S.ashx?btag=a_17172b_14837c_&affid=12824&siteid=17172&adid=14837&c=
You will see the actual result
document.write('<script type="text/javascript" src="//wlbetclic.eacdn.com/TrafficOpt/s.5.4.min.js?t=1"></script>');
document.write('<script type="text/javascript" src="//wlbetclic.eacdn.com/wlbetclic/img/js/Affiliate_12824.js?t=20160224"></script>');
//other lines omitted for brevity
So this file is executing document.write which obviously will not work in angular, just because they are totally different (even though you could trigger digest cycle somehow, you still don't have access to modify that script file, as it's generated by 3rd party server and has own variables)
What i would do is - make a page like ad.html, just like index.html or 404.html, then request this file from angular (not as template, but like a view file) as an iframe src with custom attributes
And i would use custom DOM element, and populate contents with jQuery, or with angular, look at jQuery sample below
Also i would need krux/postscribe plugin, because you cannot use document.write in async html files
<!-- create multiple holders -->
<ad-holder url="https://wlbetclic.adsrv.eacdn.com/S.ashx?btag=a_17172b_14837c_&affid=12824&siteid=17172&adid=14837&c="></ad-holder>
<div class="black-widow">
<!-- with size attributes -->
<ad-holder url="http://google.com" width="100" height="40"></ad-holder>
</div>
<!-- jQuery population with iframe -->
<script>
//get all custom elements
$('ad-holder').each(function(){
//create iframe placeholder
var $iframe = $(document.createElement('iframe'));
//get url of custom element
var url = $(this).attr('url');
//request ad.html file with params, currently it's url param
$iframe.attr('src', 'ad.html?url=' + url);
//some stylings acceptable here
$iframe.width('100px');
//or get styles from custom-element
var heightValue = $(this).attr('height');
$iframe.height(heightValue || '50px');
//rebuild custom element with iframe
$(this).append($iframe);
});
</script>
<!-- angular populate with iframe directive -->
<scrip>
angular.module('app', []).directive('adHolder', function(){
return {
restrict: 'E',
scope: { url: '#' },
//you could also execute in compile-phase
link: function(scope, element, attribute){
var $iframe = angular.element(document.createElement('iframe'));
$iframe.attr('src', 'ad.html?url=' + scope.url);
element.html($iframe);
}
}
});
</script>
And ad.html would look like
<body>
<div id="ad"></div>
<script>
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
//for the sake of simplicity we expect only 1 param (url)
return query.replace('url=', '');
}
var adUrl = getQueryVariable('url');
if (adUrl)
postscribe('#ad', '<script src="' + adUrl + '"><\/script>');
else {
var $h1 = $(document.createElement('h1'));
$h1.text('No ad available');
$(document.body).append($h1);
}
</script>
</body>
The best part of this solution is that you can reuse same custom-element with different url attribute for any other ads
Checkout jQuery real working demo
Although this demo heavily uses jQuery, it's easy to tweak for angular version, which i would suggest you to implement as homework =)
Short answer:
Angular does not perform compilation of Javascript in HTML templates. You either put the HTML manually in the page (instead of loading as template) or have another way to call it.
You can read more here

Adding angular directive with javascript files as package

I am writing a directive that I want other people to reuse.
The problem I encounter is that my directive has several js files it uses, and if I want others to use it, they need to add the js files explicitly.
Is there a way to make the directive include those files so that other will only have to add the directive file?
The way it works today is by adding the js files in the main head html file.
Can I use tamplateUrl to load the js files? Iv'e seen in THIS post that loading scripts creates some problems.
Concrete Example:
index.html:
<body data-ng-app="example">
<test-dir></test-dir>
</body>
index.js:
(function(angular){
var app = angular.module('example', []);
app.directive('testDir', function(){
return{
restrict: 'E',
templateUrl: 'test-me.html'
}
});
})(window.angular);
test-me.html:
<script type="text/javascript" src="test.js"></script>
<div> TEXT </div>
test.js:
function testMe() {
console.log('blah');
}
This format will call the directive and I will see the div TEXT text. BUT, I can't call the function testMe and I don't see any transfer in the network for test.js which is included in the directive's template.
How can I make it work?

Simplest way to use ng-include

I have been trying to write a simple angular.js app, that includes another file using ng-include. I must have done something/missed something so that the included file does not get included. I must be doing something fundamentally wrong but can't see what it is.
Here is Index.html
<!DOCTYPE html>
<html>
<head ng-app="app">
<title>Demo</title>
<script data-require="angular.js#1.2.0" data-semver="1.2.0" src="http://code.angularjs.org/1.2.0/angular.js"></script>
<script data-require="angular-resource#1.2.0" data-semver="1.2.0" src="http://code.angularjs.org/1.2.0/angular-resource.js"></script>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<div ng-controller="appctrl">
<h1>Airports</h1>
<div ng-include="'extra.html'"></div>
<h1>Airports</h1>
</div>
</body>
</html>
file extra.html contains the element to be included
<h2>Inside</h2>
and script.js is the file to initialise angular
(function () {
'use strict';
var app = angular.module('app', []);
app.run(['$route', function ($route) { // Include $route to kick start the router.
}]);
angular.module('app').controller('appctrl', [function AppCtrl() { }]);
});
I created to Plunk to demonstrate what I mean. There's not much there: the ng-app defined, references to the angular files and a couple of titles to delineate the insert point. Nothing is shown between.
What is the simplest way to use ng-include in angular.js?
Place ng-app on your body section.
Include angular-route.js (eg. <script src="http://code.angularjs.org/1.2.0/angular-route.js"></script>) and add this dependency to your app initialization (var app = angular.module('app',['ngRoute'])
Don't put your script.js code inside (function(){}). (If you want to do this, call this function (function(){})();)
Your code with changes: http://plnkr.co/edit/k1dFPeb9E2B2pjTthi1K?p=preview
This is a script of mine:
HTML:
<div id="superhero-nav-container">
<ul id="superhero-nav">
<li><a ng-click='template = templates[0]'>Biography & Stats</a></li>
<li><a ng-click='template = templates[1]'>History</a></li>
<li><a ng-click='template = templates[2]'>Powers</a></li>
<li><a ng-click='template = templates[3]'>Enemies</a></li>
</ul>
</div>
<div class="superhero-templates" ng-include src='template.url'></div>
JS in the controller:
$scope.templates = [
{ url: '/views/superheroes/biography.html' },
{ url: '/views/superheroes/history.html' },
{ url: '/views/superheroes/powers.html' },
{ url: '/views/superheroes/enemies.html' }
];
$scope.template = $scope.templates[0];
I have something like menu that changes the html in the bottom div. Hope that helps.
EDIT (for the comment below):
Your mistakes were:
Put your ng-app attribute in the html tag of the
document not in the head
Include angular-resource.js (eg. <script src="https://code.angularjs.org/1.2.15/angular-resource.js"></script>) and add this dependency to your app initialization:
angular.module('app', ['ngResource']) ...
Don't put your script.js code inside (function(){}). If you want to do this, call this
function (function(){})();
Here is your working code: Plunker

Require directive on template

I am using RequireJS in my Angular app. I would like to require my pill where it is actualy used.
pill.js
define([], function() {
angular.module('app').directive('pill', function() {
return function(a,b,c) {
b.html("A pill");
};
});
});
incl.html
<div load-script="require(['pill']);"></div>
<div pill>test</div>
main.html
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.js"></script>
<script src="http://requirejs.org/docs/release/2.1.10/comments/require.js"></script>
</head>
<body>
<script>
var app = angular.module("app", [])
app.directive('loadScript', function() {
return {
link: function(scope, element, attrs) {
(new Function(attrs.loadScript))();
}
};
}
);
</script>
<div ng-include="'incl.html'"></div>
</body>
</html>
This short example should declare a pill directive that just transform text from test to A pill inside incl.html file. However, it doesn't work. I guess it is because the pill directive is registered after incl.html is compiled.
I want avoid declaring directives somwhere globaly for example inside main.html because it is not used there. Is this requirement achievable in elegant way?
The best way to load directive on demand is to create it using $compileProvider which you will need to cache during your app.config phase. Also, instead of using ng-include, I would suggest you load the directive you need when partial view that uses it loads.
To do that, it is actually quite complicated. I created following library that should help get you started:
http://marcoslin.github.io/angularAMD/
angularAMD would make it easier for your create a independent file that allow you to configure RequireJS dependency to load the directive only on the partials that needs it.

Categories

Resources