I have a directive that I want to clear the content of a DIV and replace it with a template either in my current view or somewhere else in my app.
So say I have my template like so...
<!-- This is an experiment -->
<script type="text/ng-template" id="1.html">
<div data-ng-repeat="beatle in beatles track by $index">
Name: {{beatle.name}}, Instrument: {{ beatle.inst}}, Alive: {{ beatle.alive }}
</div>
</script>
and in my directive I have the following:
link: function (scope, element) {
element.bind('click', function () {
// clear out old template
angular.element(element).empty();
angular.element(element).html(document.getElementById('1.html'));
});
}
I seem to be able to load the template but I see the following instead of my content
[object HTMLScriptElement]
I wondering if I need to compile again or run a digest or if I am just going about this totally wrong. I also don't like using document.getElementById in my directive code, for some reason it feels wrong. Can anyone provide me with an answer to why I only see [object HTMLScriptElement] after clicking my directive and wether using document.getElementById in my directive is acceptable or if there is a better command to load the content...
Here is a fiddle of the whole app... or a bin! https://jsbin.com/yizupa/edit?html,output
In the meantime I have just came to the conclusion that my setup / implementation is wrong and that I should consider another way to implement such a feature.
here, i have create one running demo.. for route using **text/ng-template**..
index.html
-------------
<!DOCTYPE html>
<html lang="en" ng-app="singlePageApp">
<script src="js/angular.min.js"></script>
<script src="js/angular-route.min.js"></script>
<script src="js/app.js"></script>
<head>
<meta charset="UTF-8">
<title>AngularJS Routing Template..</title>
</head>
<body>
<div ng-controller="singlePageAppController">
{{message}}
</div>
<ul>
<li>Home</li>
<li>About</li>
</ul>
<div ng-view="showOutput"></div>
</body>
<script type="text/ng-template" id="home.html">
This is HOME Page..
</script>
<script type="text/ng-template" id="about.html">
This is ABOUT Page..
</script>
</html>
--------
app.js
--------
var app=angular.module('singlePageApp',['ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when('/home',{
controller:'singlePageAppController',
templateUrl: 'home.html'
})
.when('/about',{
templateUrl: 'about.html'
});
});
app.controller('singlePageAppController',function($scope){
$scope.message="Hello Single Page Application..";
});
Related
i'm using Angularjs and I have a ng-view with some parts. The partial views have some scripts in the head.
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
...
</head>
<body>
<div class="section">
... some content
</div>
</body>
</html>
If i load a view those scripts are loaded too.
<div style="" class="ng-scope" ng-view="">
<meta class="ng-scope" charset="utf-8">
<script class="ng-scope" type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div class="section ng-scope">
.. some view content.
</div>
</div>
I'm using an HTML Editor for Twitter Bootstrap to edit views quickly and this tool needs the html, head and body tags. And I don't want to remove them from templates. Is it posible to ignore the head tag of partial view when it's loaded?
Instead of using a ng-view, isn't better to create a directive with your template in, and use the compile() or in the link() phase to remove the bad tags ?
Afaik directives are the good way to alter the DOM.
I'm not really familiar with the compile() but I let you read this post if you are interested in : http://www.bennadel.com/blog/2794-when-do-you-need-to-compile-a-directive-in-angularjs.htm
I got it. I took a look into templateRequestProvider and httpProvider. And Here is my solution.
app.config(function($routeProvider, $httpProvider) {
....
function appendTransform(defaults, transform) {
// We can't guarantee that the default transformation is an array
defaults = angular.isArray(defaults) ? defaults : [defaults];
// Append the new transformation to the defaults
return defaults.concat(transform);
}
/**
* My HTML Template transformation
*/
function doTransform(value){
if(angular.isString(value)){
return value.replace(/<head>(.|\n)*<\/head>/mg,"");
}
return value;
}
$httpProvider.defaults.transformResponse = appendTransform($httpProvider.defaults.transformResponse,
function(value) {
return doTransform(value);
});
})
It's not a best solution because it would filter each http request. Better to apply it only for ng-view. It should work with templateRequestProvider.httpOptions but only with angular 1.5+.
I want to manage my controller specific to an ng-view page, therefore I put the controller in ng-view page and used that controller specific to that page only. However, the code does not show what it should show from that controller.
Here is my case.
I split my code into 3 files, which are "mainfile.php", "page1file.php", and "page2file.php". "mainfile.php" contains main page which routes to page 1 and page 2. To compare the results, I created different conditions for those 2 pages. "page1file.php" uses controller which has been defined in "mainfile.php", while "page2file.php" uses controller which is defined in the page itself.
In this circumtances, "page1file.php" successfully shows what I want, but "page2file.php" does not show what it should show. Please help me and give a very simple explanation and a simple solution since I'm very new to angularjs.
Here is my code. You can just copy them and run it on your php server.
mainfile.php :
<!DOCTYPE html>
<html>
<head>
<title>learn angular routing</title>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.min.js"></script>
<script type="text/javascript">
function routeReload($scope) {
$scope.routeReloading = function(){
window.location.reload();
};
}
routeReload.$inject = ['$scope'];
function routeConfig($routeProvider) {
$routeProvider
.when('/one',{
templateUrl:'page1file.php'
})
.when('/two',{
templateUrl:'page2file.php'
})
;
}
routeConfig.$inject=['$routeProvider'];
function testOne($scope) {
$scope.name = "page one";
}
testOne.$inject = ['$scope'];
var testNgView = angular.module('testNgView',['ngRoute']);
testNgView.config(routeConfig);
testNgView.controller('routeReload',routeReload);
testNgView.controller('testOne',testOne);
</script>
</head>
<body>
<div ng-app="testNgView">
<div ng-controller="routeReload">
View page <a ng-click="routeReloading();" href="#one">one</a> or
<a ng-click="routeReloading();" href="#two">two</a>
<div ng-view></div>
</div>
</div>
</body>
</html>
page1file.php :
<div ng-controller="testOne">
This is {{name}}
</div>
page2file.php :
<script type="text/javascript">
function testTwo($scope) {
$scope.name = "page two";
}
testTwo.$inject = ['$scope'];
testNgView.controller('testTwo',testTwo);
</script>
<div ng-controller="testTwo">
This is {{name}}
</div>
I don't think you can inline script modules in your view templates. Have a look at this working version of your app, the way I would organize it:
http://plnkr.co/edit/nSsagK1Y04akNJyMToah?p=preview
You can use .php files in place of the .html files, that shouldn't make a difference.
So your main file should look something like this:
<!DOCTYPE html>
<html>
<head>
<title>learn angular routing</title>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.min.js"></script>
</head>
<body>
<div ng-app="testNgView">
View page one
or two
<ng-view></ng-view>
</div>
<script src="app.module.js"></script>
<script src="app.routes.js"></script>
<script src="views/page1/controller.js"></script>
<script src="views/page2/controller.js"></script>
</body>
</html>
If your goal is to use PHP to dynamically render your controllers, see the answer to this SO question: Angularjs: server side (php) rendering and data binding client side after an event
You may also be interested in this article, about loading Angular components after the application has been bootstrapped: http://www.bennadel.com/blog/2553-loading-angularjs-components-after-your-application-has-been-bootstrapped.htm
TL;DR: You would need to store a reference to $controllerProvider in the config phase, and then call $controllerProvider.register('MyController', MyController) in your inline script. I'm not sure how I feel about that though...
I've been trying to link up components of a simple Angular app but cannot seem to get my initial view state to load. One main issue seems to be that I can't even log inside of my .config setup (despite making sure that everything is syntactically correct). As far as I can tell (after some testing) all of my files are in the right locations).
Anybody see any glaring mistakes?
index.html:
<!DOCTYPE html>
<html>
<head></head>
<title>Thing</title>
<body class="container">
<div class="row">
<div class="span12">
<div class="well" ui-view></div>
</div>
</div>
<!-- dependencies -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js"></script>
<script src="//angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<!-- css files -->
<!-- application files -->
<script src="js/app.js"></script>
<script src="js/payments.js"></script>
<!-- Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places"></script>
</body>
</html>
app.js:
var paymentApp = angular.module('paymentApp', ['ui.router'])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/payments')
// Now set up the states
console.log("in config")
$stateProvider
.state('payments', {
url: "/payments",
templateUrl: "view/payments.html"
})
});
payments.html:
<h1>Payments Page</h1>
<div class="buttons">
<button>Click Me!</button>
</div>
<div class="search"></div>
<div class="payments"></div>
Quite a simple mistake to make - you have forgotten to bootstrap your angular app.
You need to add the ng-app directive somewhere and point it to your module.
E.g.
<html ng-app="paymentApp">
https://docs.angularjs.org/api/ng/directive/ngApp
Angular is working as I can see the {{ text }} but I can't seem to get the ng-view to display.
My code is:
index.html:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://code.angularjs.org/1.3.5/angular.js"></script>
<script src="https://code.angularjs.org/1.3.5/angular-route.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app='app'>
<div class="main_container" ng-controller="MainController">
<span ng-cloak>{{text}}</span>
<div ng-view></div>
</div>
<!-- modules -->
<script src='app.js'></script>
<!-- controllers -->
<script src='MainController.js'></script>
<script src='home.js'></script>
</body>
</html>
home.js:
app.controller('home', function($scope) {
$scope.words = 'It works!';
});
MainController:
app.controller('MainController',function($scope){
$scope.text = 'Hello World!';
});
home.html:
<div ng-controller="home">
<h3>{{ words }}</h3>
</div>
app.js:
var app = angular.module('app', ['ngRoute']);
app.config(function($routeProvider, $locationProvider){
$routeProvider.
when('/index',{
templateUrl: 'home.html',
controller: 'home'
}).
otherwise({
redirectTo: '/index'
});
//$locationProvider.html5Mode(true);
});
edit:
It seems to work in plunker but when I open the file in chrome I get the following error:
"XMLHttpRequest cannot load {{file location}}. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource."
You don't need the ng-controller attribute on your root element in home.html because you are already defining the controller for that template when you set up your $routeProvider. Beyond that your code looks good. If you really want to get ahead of the game, though, I would recommend using UI Router if you plan to do any advanced routing in your application. It is much more robust and easier to work with than Angular's ngRoute, widely used, and well-documented.
Your Code is working fine !! there may be problem on which file to load first so please take care of the order of the files added in your HTML
Here is the working plunker with your code. here ng-view loads with no problem
http://embed.plnkr.co/oNADizOltrGitbWTWNXf/preview
Hope this helps!!!
Very new to AngularJS, I am guessing the term for what I am trying to do is lazy load. I have looked at several different blogs and I have not found a complete working solution that is purely using AngularJS.
I understand that if I put the <script src="js/process1.js"></script> in index.html, all works fine, I am trying to cut down on the amount of js that is pulled down on the initial load.
With the script tag sitting in the partial, it is never loaded so the P1Ctrl is never created. So currently, if a user go into the application and never goes to process55, the user still has the code there for process55 even though it was never used.
Is there a way to load the file and inject the objects created in the process1.js into the app defined in main, at the time process1 route is executed?
index.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Large Angular App</title>
<link rel="stylesheet" href="lib/foundation/css/foundation.min.css" />
</head>
<body ng-app="largeApp" ng-controller="LargeAppController">
<div>
Home | Process1
</div>
<br/>
<br/>
<br/>
<ng-view>Test</ng-view>
<script type="text/javascript" src="lib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="lib/angular/angular-route.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
js/main.js:
var app = angular.module("largeApp", ['ngRoute']);
var appCtrl = app.controller("LargeAppController", function(){});
app.config(function ($routeProvider, $controllerProvider) {
// save references to the providers
app.registerCtrl = $controllerProvider.register,
$routeProvider.when('/', {templateUrl: 'partials/home.html'});
//Thinking I need to set up a resolve to fire off a script loader to load js.
$routeProvider.when('/process1', {templateUrl: 'partials/process1/process1.html'});
$routeProvider.otherwise({redirectTo: '/'});
});
partials/home.html:
<div>
Home Page
</div>
partials/process1.html:
<script type="text/javascript" src="js/process1/Process1Controller.js"></script>
Process 1 {{process1data}}
js/process1.js:
console.log("I made it here");
app.registerCtrl('Process1Controller',function($scope){
$scope.process1data = "Hello!";
}
]);
To implement lazy loading of controllers in simple way, you have to do the following:
Save $controllerProvider.register (which is the only method to add a controller into already bootstrapped AngularJS app) to variable in your app (main.js):
var app = angular.module('app',["ngRoute"]);
app.config(['$routeProvider', '$controllerProvider',
function($routeProvider, $controllerProvider) {
// remember mentioned function for later use
app.registerCtrl = $controllerProvider.register;
//your routes
$routeProvider.when('/', {templateUrl: 'partials/home.html'});
$routeProvider.when('/process1', {templateUrl: 'partials/process1.html'});
$routeProvider.otherwise({redirectTo: '/'});
}
]);
process1.html:
<script src="js/process1.js"></script>
<div ng-controller="P1Ctrl">
{{content}}
</div>
And now, in process1.js you use our registerCtrl:
app.registerCtrl('P1Ctrl', function($scope)
{
$scope.content = '...';
});
index.html probably remains the same. Check if your process1.js is being loaded (simply using console.log() right in the body of process1.js, not in P1Ctrl controller). If it isn't, include jQuery before Angular:
<script src="lib/jquery/jquery.js"></script>
<script src="lib/angular/angular.js"></script>
IMPORTANT: This method doesn't work with angular 1.2.0-rc.2 and 1.2.0-rc.3, because this little trick with jQuery doesn't work.
For more complex (and prettier) solution, with .js files as dependencies in route definitions, check that article: http://ify.io/lazy-loading-in-angularjs/ - it also works with rc.2 and rc.3. Here is plunk implementing described method: http://plnkr.co/edit/ukWikO5TVDtQ1l9WlrGD