templateUrl not working - javascript

I was just testing basic angular code, and I had everything working with only template, but not with templateUrl. I don't include previous code because everything else was working EXECEPT for when I changed to templateUrl and moved everything in my previous template to an external HTML. Could this be a problem with accessing addition HTML files?:
In my HTML,
<header></header>
In my JS,
...
restrict: 'E',
templateUrl: '/journal/journalcontent.html'
In journalcontent.html,
<div>
...
</div>

Check the network tab from developer tools.
What AngularJS does is to take "/journal/journalcontent.html" and tries to check in the $templateCache helper - if it doesn't find it loaded there already, it will try to download it based on current URL - and this should be visible with a 404 or 200 in your network tab.
If your user responsiveness is really important and it's a reusable template, you could consider to define it in your HTML:
<script type="text/ng-template" id="/journal/journalcontent.html">
<div>my stuff</div>
</script>

Related

Changing route doesn't show anything

I'm doing a web page, I'm quite newbie using Angularjs. I've changed the architecture in order to use ng-view and move dynamically through the subpages. And when the route is /project nothing happens and moreover there is no error on the console.
In chrome when I inspect the element it appears as
<!-- ngView: -->
Thanks in advance.
index.html:
<html lang="en" ng-app="innhomeweb">
...
<div ng-view></div>
app.module.js:
var Appmodule = angular.module('innhomeweb', [
'projectList',
'callList',
'organizationList',
'searchList',
'adminModule',
'transformModule',
'ngRoute',]);
Appmodule.config(['$locationProvider' ,'$routeProvider',
function config($locationProvider, $routeProvider) {
$routeProvider.when('/project', {
template: '<project-list></project-list>',
controller: 'projectList'
});
}
]);
I had a similar problem a while ago. Try adding $locationProvider.hashPrefix('!'); right before your $routeProvider.when() to configure the deep linking and .otherwise('/project'); right after it to set the default path.
The AngularJS tutorial claims that "setting a prefix is not necessary", but I wasn't able to get it to work without it.
It's because you specified a little strange template in $routeProvider, just try to replace it by, for example, template: '<h1>TEST</h1>', and it should work fine.

How to create a messaging service across application in Angular JS?

I want to show messages to the end user, just like Google, at the top center of the web panel.
I don't want to include the HTML and related script everywhere in every form and list and chart that I have. I want to centralize this messaging functionality into a service (in Angular JS term) that can be used everywhere.
And just like Google, I want to be able to show rich text in my messages, that is, I want to include links and probably other HTML stuff there. For example instead of showing Customer is defined, I want to show Customer is defined, <a href='#/customer/addPhone'>Now add a phone</a> to guide the user.
What I've done is to place the messages HTML in the root layout of my single paged application:
<div class="appMessages">
<span ng-show="message" ng-click="clearMessage()" ng-bind-html="message"></span>
</div>
and in our controllers, we inject the $rootScope and try to set the message property on it.
Yet I get no results. Can you guide me please?
As a general best practice I would avoid using $rootScope to pass the messages but rather use a dedicated service to update the message,
On your case the problem might be that you need to use angular $sce service to mark your html as trusted.
or load ng-santizemodule instead (which is a seperate module you need to load see offical doc)
That is needed because angular security requires you to explicitly check the html, if the source of your messages are from your code only, and not users inupts you can use the trustAsHtml as you know for sure it a safe html.
On your controller inject $sce, and bind it to your scope, and then use the $sce.trustAsHtml(value) function.
<div class="appMessages">
<span ng-show="message" ng-click="clearMessage()" ng-bind-html="$sce.trustAsHtml(message)"></span>
</div>
angular.module('app', [])
.component('message', {
controller: function($sce, messagService){
this.messagService = messagService;
this.$sce = $sce;
},
template: '{{$ctrl.message}}<div ng-bind-html="$ctrl.$sce.trustAsHtml($ctrl.messagService.message)"></div>'
})
.service('messagService', function(){
this.message = '';
this.updateMessage = function(message){
this.message = message;
}
})
.controller('mainCtrl', function($scope, messagService){
$scope.updateMessage = function () {
messagService.updateMessage('wow <b style="color:yellow;">shiny</b> message');
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-controller="mainCtrl" ng-app="app">
<message></message>
<button type="button" ng-click="updateMessage()"> update message</button>
</div>

How multiple ng-app worked in angular (Why such behaviour?)

I tried giving two ng-app in an application , when i gave two ng-app like
<body>
<div ng-app="A">
<div ng-controller="AC">
</div>
</div>
<div ng-app="B">
<div ng-controller="BC">
</div>
</div>
</body>
Then second ng-app does not work.
But when i change the scope of first ng-app="A" from div to body then both works fine like
<body ng-app="A">
<div>
<div ng-controller="AC">
</div>
</div>
<div ng-app="B">
<div ng-controller="BC">
</div>
</div>
</body>
Can anyone let me know why this behavior as i am quite new to angular.
I wanted to know why it worked as i didn't called angular.bootstrap on the second one.I tried searching but i didn't got how it is working when changing the scope of ng-app from div to body.
Find the fiddle for the same https://jsfiddle.net/maddyjolly2112/wyfd0djp/1/ and mind copying the js into the same .
Docs say: Don't use ngApp when instantiating multiple angular applications.
The reason you can't do this is laid out in the docs for the ngApp directive.
Only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead. AngularJS applications cannot be nested within each other.
But Bootstraping multiple Angular apps is possible...
To bootstrap multiple Angular apps, you have to reference each, and they logically can't be nested, or sharing an element; they need to be separate from each other. Because of this, you cannot use the directive, ngApp:
<html>
<head></head>
<body>
<script src="angular.js"></script>
<div id="appElementA"></div>
<div id="appElementB"></div>
<script>
var app = angular.module('A', [])
.controller('AB', function($scope) {
$scope.greeting = 'Welcome!';
});
var appElementA = document.getElementById('divAppA');
angular.bootstrap(appElementA, ['A']);
var bApp = angular.module('B', [])
.controller('BB', function($scope) {
$scope.greeting = 'Welcome to B app!';
});
var appElementB = document.getElementById('divAppB');
angular.bootstrap(appElementB, ['B']);
</script>
</body>
</html>
The above code would be how you'd do it for your apps. You'd then have to be sure you're assigning the controllers to the right angular application (app vs bApp, in the above example.)
But don't nest them!
You claim it 'works' when you nest them, but you should be aware that it doesn't work, it just doesn't crash hard. Don't have multiple angular applications nested. You'll encounter weird issues, especially if you have multiple variables named the same bound to the $rootScope.
But you can nest them without ill effects, right?
If you're intent on having two Angular apps nested; it's possible but extremely version specific and liable to break in weird ways. This Stack Overflow answer talks about it.
From Angular's official docs :
Only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead. AngularJS applications cannot be nested within each other.
Source : https://docs.angularjs.org/api/ng/directive/ngApp
If the question is : why the second example works and not the first, the answer is in the link above > Angular needs the first ngApp to be placed near the root element of the page (html or body).
As George mentioned, manual bootstrapping will work.
In html, use id instead of ng-app.
In script
var dvFirst = document.getElementById('dvFirst');
var dvSecond = document.getElementById('dvSecond');
angular.element(document).ready(function() {
angular.bootstrap(dvFirst, ['firstApp']);
angular.bootstrap(dvSecond, ['secondApp']);
});
Here is a working plunker
http://plnkr.co/edit/1SdZ4QpPfuHtdBjTKJIu?p=preview

How to print to console.log from inside Angular.js inline-template's script tag?

I'm trying out the inline-template of Angular.js. I would like to have a way to debug Angular objects by printing to the console whenever an html page is rendered.
The inline-template puts html templates inside script tags. For example:
<script type="text/ng-template" id="/htmlpage.html">
<div class="page-header">
<h1>Title</h1>
</div>
<!-- everything else here is html too -->
</script>
It's tricky because the stuff inside the script tags is not really JavaScript anymore. So I don't know how to printing to the console inside the htmlpage.html with inline-template.
I have tried but failed with nesting a script tag:
<script type="text/ng-template" id="/htmlpage.html">
<!-- html page template Angular stuff before is okay -->
<script>console.log("this line DOESN'T SHOW UP anywhere");</script>
<!-- html page template Angular stuff AFTERWARDS ALL FAIL-->
</script>
I also tried just throwing in a bare console.log, since it's inside a script tag.
<script type="text/ng-template" id="/htmlpage.html">
<!-- rest of html page template is okay -->
console.log("this entire line gets output as text on the html page");
<!-- rest of html page template is okay -->
</script>
but the entire line, console.log("this entire line gets output as text on the html page");, gets printed out to the html page, not the console!
You can achieve this by calling some debugging function defined in the controller scope with ng-init in the template definition. See this example.
Let's say the template is defined by
<script type="text/ng-template" id="myTemplate.html">
<div ng-init="log('In template: '+$index)">{{greet}} Melissa<div>
</script>
and you have a controller defined as
var app = angular.module('myApp', [])
.controller('myController', ['$scope', '$log', function($scope, $log) {
$scope.greetings = ["Hello", "Bonjour", "Guten tag"];
$scope.log = function(message) {
$log.debug(message);
}
}]);
then
<ul ng-controller="myController">
<li ng-repeat="greet in greetings">
<div ng-include src="'myTemplate.html'"></div>
</li>
</ul>
should print in the console
In template: 0
In template: 1
In template: 2
The ng-init is called each time a template is instantiated. I just log some values available in the scope, like $index which is the index in the ng-repeat loop.
See this example.
Using the above answer, I found the following simpler.
The easiest solution for me was to temporarily set $scope.console = console in my controller, letting the template have access to the window.console global variable and its associated functions as normal, through the $scope binding
Because the templates are tightly scoped, they do not have access to global and window variables, as a result console.X() is not available from the template. And, like you probably experienced, attempting to reference undefined values from within the template did not result in an error, just... nothing. (Cue tearing hair out trying to figure out why events aren't firing)

AngularJS <a> tag links not working

I have an index of objects returned from search. The template has an ng-repeat where the item's URL is constructed from data in the model but in the final markup the "a" tag does not work. The ng-href and href are correct, the URL bar changes when the link is clicked but the page does not load. Doing a browser refresh after the click does get the page. So something in Angular is changing the URL bar but not triggering a load???
Can't make this reproduce in a jsfiddle because the problem seems to be in loading the json into the template after a $resource.query() function, which I can't do from a jsfiddle. With a simulated query loading static data the jsfiddle works even though the final markup looks identical.
The AngularJS template looks like this:
<div ng-controller="VideoSearchResultsCtrl" class="row-fluid">
<div class="span12" >
<div class="video_thumb" ng-repeat="video in videos">
<p>
<a ng-href="/guides/{{video._id}}" data-method="get">
<img ng-src="{{video.poster.large_thumb.url}}">
</a>
</p>
</div>
</div>
</div>
The results look fine and produce the following final markup:
<div ng-controller="VideoSearchResultsCtrl" class="row-fluid ng-scope">
<div class="span12">
<!-- ngRepeat: video in videos --><div class="video_thumb ng-scope" ng-repeat="video in videos">
<p>
<a ng-href="/guides/5226408ea0eef2d029673a80" data-method="get" href="/guides/5226408ea0eef2d029673a80">
<img ng-src="/uploads/video/poster/5226408ea0eef2d029673a80/large_thumb_2101146_det.jpg" src="/uploads/video/poster/5226408ea0eef2d029673a80/large_thumb_2101146_det.jpg">
</a>
</p>
</div><!-- end ngRepeat: video in videos -->
</div>
</div>
The controller code is:
GuideControllers.controller('VideoSearchResultsCtrl', ['$scope', '$location', 'VideoSearch',
function($scope, $location, VideoSearch) {
$scope.videos = VideoSearch.query({ namespace: "api", resource: "videos", action: 'search', q: $location.search().q });
}
]);
Using AngularJS 1.2-rc.3. I've also tried using an ng-click and regular old onclick to get a page loaded even with static URL but the clicks never trigger the code. BTW static non-angular links on this page do work, so the Menu Bar and Sign Out work.
What have I done wrong here or is this a bug in AngularJS?
From the mailing list I got an answer:
Have you by any chance configured your $locationProvider to
html5Mode? If yes this would cause your problems. You could force it
to always go to the url by adding target="_self" to your tag. Give
it a shot.
I had configured to use HTML5 so adding the target="_self" to the tag fixed the problem. Still researching why this works.
Not sure if this has been updated since this post was answered, but you can configure this in application startup. Setting the rewriteLinks to false re-enables your a tags, but still leaves html5mode on, which comes with all its own benefits. I have added a bit of logic around these settings to revert html5mode in browsers where window.history is not supported (IE8)
app.config(['$locationProvider', function ($locationProvider) {
if (window.history && window.history.pushState) {
$locationProvider.html5Mode({
enabled: true,
requireBase: true,
rewriteLinks: false
});
}
else {
$locationProvider.html5Mode(false);
}
}]);
Angular Docs on $locationProvider
The benefits of html5mode vs hashbang mode
I know this post is old, but I recently ran into this problem as well. My .html page had the base
//WRONG!
<base href="/page" />
and the fix:
//WORKS!
<base href="/page/" />
notice the forward-slash ('/') after 'page'.
Not sure if this applies to other cases, but give it a try!
AngularJS suffers from a sparse documentation, I hope their gaining momentum will improve it. I think AngularJS is primarily intended as a SPA, and maybe the idea behind deactivating by default all a tags allows one to easily incorporate angular into some already existing html.
This allows for quick refactoring of the default "routing" behaviour of a "traditional" website (well, script pages linked between each other) into the angular routing system, which is more of an MVC approach, better suited for Web Apps.
Find this line:
$locationProvider.html5Mode(true)
change it for:
$locationProvider.html5Mode(true).hashPrefix('!')
and include this line in the head of index.html if you don't have it.
<base href="/">
I see this is old, but this is one of the top results on Google.
So if you are using Angular 7, and only want to link a couple of files, then just put the into the "assets" directory:
Now when you want to link the file you can just use the href tag as below:
<img src="assets/ang_1.png" alt="Angular">
Note: you can only link to the assets folder by default, so you strictly have to place your files there.

Categories