AngularJS controller is being called twice - javascript

I new in AngularJS. I am learning AngularJS. I am trying to follow different tutorials. I working with some codes now. I have a question in this regard. My codes ares as below
index.html
<html ng-app="main_app">
<head>
<title>AngularJS Application</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
<script src="js/route.js"></script>
</head>
<body ng-controller="main_controller">
<div ng-view></div>
</body>
</html>
route.js
var app = angular.module('main_app',['ngRoute']);
app.config(function($routeProvider)
{
$routeProvider
// route for the home page
.when('/', {
templateUrl : 'pages/home.html',
controller : 'main_controller'
});
});
app.controller('main_controller', function($scope)
{
alert('Yes');
});
If I run this code I get the alert('Yes'); twice.
Why I am getting this alert twice ?? Is it normal action or I am doing something wrong ??
Thanks
Update
#Leo Farmer I changed structure of index.html as belows
<html>
<head>
<title>AngularJS Application</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
<script src="js/route.js"></script>
</head>
<body>
<div ng-app="main_app">
<div ng-controller="main_controller">
<div ng-view></div>
</div>
</div>
</body>
</html>
But still I am getting alert() twice. Actually my concern is "Am I doing wrong or right ??" I think getting alert() twice means I am doing something wrong.
Is my structure following good convention ??
Thanks

Your controller is getting called twice. You have it in your body element (that's alert number one) then you also assign it as your controller for your pages/home.html which you call as your partial (that's alert two).
You don't need it in your body element. I recommend you take it out of there.

In my case, I have used <div id="userregistration" class="content-wrapper" ng-controller="UserRegistrationController"> in html and in $route also so it called twice. I removed in html after that it is fixed

I would reccomend modifying your alert code so it is triggered by a button or another event. You're seeing the asynchronous calling of a controller that, due to the times of which loading and processing your page, causes that code to be run twice.
I would first try loading your Javascript at the bottom of your body so that the entire page is loaded before JavaScript is.
Alternatively, you could try adding a timeout using the $timeout service to delay running your alert for a short time until the entire page loads.

Because:
You are using same controller in anguler route module and ng-controller directive in the template. If you use a controller in the route module while configuring, it is useless to use same controller with ng-controller in the template. ng-view directive is enough here.
Since you are using same controller both in route config and ng-controller, thats why you are getting alert twice. You should use your controller either in angular route or ng-controller directive
If you remove routing option, you will get alert only once.

Related

window.open() doesn't work correctly inside a JS function

I tried to create an updates list for my web, so that when I click on the relevant update- a new additional small html window will open and I will see the full update content.
This is the code I wrote:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="script.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body ng-app="myApp">
<p ng-controller="updatesCtrl">
<span ng-repeat="x in updates">
● {{x.title}}
<br><br>
</span>
</p>
<script>updates();</script>
</body>
</html>
script.js:
function updates(){
angular.module('myApp', []).controller('updatesCtrl', function($scope) {
$scope.updates = [
{title:"update1",update:"update1 content"},
{title:"update2",update:"update2 content"}
];
});
}
function showUpdate(title, update){
var win=window.open('updateWindow.html','newwindow','width=600, height=350');
win.document.getElementById("title").innerHTML=title;
win.document.getElementById("update").innerHTML=update;
return false;
}
updateWindow.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1 id="title"></h1>
<p id="update"></p>
</body>
</html>
I have few problems here:
1.When I clicked on the update link, the update window replaced the main page (index.html) window, and also was a full size page.
2. No change was made in the <h1> and the <p> of the updateWindow- although I wrote a script that was suppose to enter an html content to those places.
I don't understand why I didn't get what I expected with this code. Especially, I don't understand the first problem: if I only try to replace the onclick content inside index.html with this: "window.open('updateWindow.html','newwindow','width=600, height=350'); return false;" - I get a new additional window with a smaller size as expected (I won't get the update content inside this window, but at least that solves my first problem).
What is the problem with my code?
Try to use window.open('updateWindow.html','_blank','width=600, height=350'); instead
it looks to me that the window is not loading before you try to update html:
you can see that the html page has not even loaded yet and the dev tools says there is a Uncaught TypeError: Cannot set property 'innerHTML' of null try getting the new page to update it onloadin the update page.

angularjs error, binding doesn't work with this keyword

Couldn't get start with angularjs, need help.
My app.js
var app = angular.module('cartApp', ['ui.router']);
app.controller('dashboardCtrl', function() {
var dash = this;
dash.something = "something";
});
index.html
<!DOCTYPE html>
<html lang="en" ng-app="cartApp">
<head>
<meta charset="UTF-8">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.1/angular-ui-router.js"></script>
</head>
<body ng-controller="dashboardCtrl">{{something}}
/body>
</html>
I think I messed up but don't know where is it.
You have all your bindings available inside controller context(this), so you should use controllerAs pattern to get binding available in this on the view. There you will be using controller alias inside ng-controller directive & you should use dash to get controller binding.
<body ng-controller="dashboardCtrl as dash">
{{dash.something}}
</body>
Also make sure you have referred app.js on the page.
could you try in controller?
app.controller('dashboardCtrl', function($scope) {
$scope.something = "something";
});
For future references, I suggest to follow this great tip.
It's very useful because provide better readability and avoid make these kinds of mistakes.

Propagating events from d3.js to angular without resorting to scope.apply

I am using the d3.js library inside an angular 1.x controller.
My d3.js library creates a click event on a div and when the div is clicked, it updates something on the angular controller's scope.
The problem is, when I change the scope ($scope.test = "a test"), the modification is not reported into the template.
However, if, inside that d3.js click event, I do a $scope.$apply (as suggested by this related topic: Angular + D3 - Get scope values to show in template from click event), the dom is updated and everything works fine.
Since the use of scope is discouraged, is there another solution that will make the changes appear in my template?
Here is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.1/d3.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>
</head>
<body>
<div ng-app="app" >
<div id="main" ng-controller="main">
test is {{test}}
<div id="graph">
hello
</div>
</div>
</div>
</body>
<script type="text/javascript">
var app = angular.module('app',[]);
app.controller('main', function($scope){
$scope.force_refresh = function(){}
d3.selectAll("#graph").on("click", function() {
$scope.test = "a test";
//////////I would like to avoid this/////////////
$scope.$apply(); ////////////////////
//////////I would like to avoid this/////////////
});
});
</script>
</html>

AngularJS ng-controller in html root element

I have an AngularJS document where I need to set fields in various parts of the document. This includes e.x. the <title> tag. So my document Looks like the following:
<html ng-app="test" ng-controller="TestCtrl">
<head>
<title>{{test1}}</title>
</head>
<body>
<h1>{{test1}}</h1>
...
</body>
</html>
As you can see I put the ng-controller in the <html> tag because I need to use the same scope across <head> and <body>. I could also set the controller on the individual elements but since I'm doing some POST and GET queries I think it's not a good idea because then they are performed multiple times.
Is using the ng-controller tag in the <html> element a good idea (is there a negative impact)? Are there better solutions?

Set a variable from ng-view

I am trying to learn AngularJS and I came across a problem where I have difficulties to solve it.
I have small application based on this template.
<!doctype html>
<html lang="en" ng-app="fff">
<head>
<meta charset="utf-8" />
<head>
<body class="{{bodyClass}}">
<div ng-view></div>
<script src="/static/js/all.js"></script>
</body>
</html>
I would like to change bodyClass in ng-view. What is the best practice solution such a case?
The variable used in your body must come from some controller. Inside ng-view you will most likely also have a page with a controller. This controller is now a child of the 'body' controller. This means that you can access parent variables from your 'child' controller.
Please read this: Scopes. The is a very, very good read about scopes. I even think this is a must read.
You could try this using route change by putting controller there
app.run(function($rootScope) {
$rootScope.$on('$routeChangeSuccess', function(ev,data) {
if (data.$route && data.$route.controller)
$rootScope.controller = data.$route.controller;
})
});
and change <body class="{{bodyClass}}"> to <body ng-class="controller">
Check http://plnkr.co/edit/fR6gSqeXbROl410tgzPJ?p=preview
The easiest would be to take object and define the bodyClass over it. Something like
$scope.appStyles={bodyClass:'default'}
This property should be defined over a controller defined on parent of ng-view html.
Now you would get this appStyle object in all ng-view scope,as they inherit the parent $scope. Which also means you can change it anywhere like
$scope.appStyles.bodyClass='newClass';
A better approach would be to move these settings into a service and share.

Categories

Resources