Angular Service method is called twice? - angularjs

I have a simple service:
angular.module('sf').factory 'sfStatic2', ->
{
doSomething: ->
console.log('called-x')
43
}
angular.module('sf').controller 'UserRegisterCtrl', ($scope,sfStatic2) ->
$scope.timezoneX = sfStatic2.doSomething()
In the console I see two times 'called-x', do you know why is this happening ? I am using angular 1.3.15

This could be occuring due to controller being called two times.
Make sure you are writing controller only once.
write either in ng-controller or in your config route.
route config (usually, app.js):
app.config(['$routeProvider', function($routeProvider){
$routeProvider.when('/',
{
templateUrl: 'pages/home.html'
//Remove controller from here
});
}]);
home.html
<!-- Add the ng-controller in your view -->
<div ng-controller="MyItemsController">
<!-- Your stuff -->
</div>

Related

isotope.js - initialize after Angular rendered DOM

Well, this is giving this angular newbie some gray hairs:
My regular isotope external javascript initialization begins like normal :
$(document).ready(function() {
// ISOTOPE INITIALISATON AND STUFF HERE
And that all works fine with no angular. Now since my isotope items is in a separate portfolio.html page which loads into my main index.html page which contains an ng-view div, isotope sometimes fails to initialize.
It's around fifty fifty: If I refresh isotope works, then it doesn't. So this is due to that angular is not ready renderinng the DOM. And so even though I am waiting for document ready (and tried document load), that does not work either.
Is there a simple way that I can create my isotope AFTER that my index.html page loaded my portfolio.html page in (where my portfolio contains my isotope divs), with Angular?
Please note I am not using angular-isotope but just the regular metafizzy isotope and angular.
A simple as possible solution would be great:
Somehow I must create my isotope after that the Angular is done. But how do I call a method in my main.js file(which is the file where I initialize my Isotope) from my Script.js file (which is the file with my Angular script)
If it is any help this is my angular script:
// script.js
// create the module and name it scotchApp
// also include ngRoute for all our routing needs
var scotchApp = angular.module('scotchApp', ['ngRoute']);
// configure our routes
scotchApp.config(function($routeProvider) {
$routeProvider
// route for the home page
.when('/', {
templateUrl : 'pages/home.html',
controller : 'mainController'
})
// route for the about page
.when('/about', {
templateUrl : 'pages/about.html',
controller : 'aboutController'
})
// route for the contact page
.when('/contact', {
templateUrl : 'pages/contact.html',
controller : 'contactController'
});
});
// create the controller and inject Angular's $scope
scotchApp.controller('mainController', function($scope) {
// create a message to display in our view
$scope.message = 'Everyone come and see how good I look!';
});
scotchApp.controller('aboutController', function($scope) {
$scope.message = 'Look! I am an about page.';
});
scotchApp.controller('contactController', function($scope) {
$scope.message = 'Contact us! JK. This is just a demo.';
});
Hmmm.hmmmm. I think it is time for a cup of tea. Hmm. hmm
Look forward to your replies!
I solved it myself.
I simply added this line to my isotope javascript file
$(window).load(function() { window.setTimeout(onRenderReadyStartIsotope, 0) });
And the intialised isotope with that timedout function call. Was no need for me this time to look into directives or change the angular, the DOM now renders, the isotope begins.

Resolve variable for ng-included view

This is my app.js:
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'partials/home.html',
controller: 'homeController',
resolve: {
loggedUser: getLoggedUser
}
}]);
The function getLoggedUser() returns a promise which is resolved in userService when it has found the logged in user. In my index.html I include a navigation bar:
<ng-include src="'partials/navbar.html'" ng-controller="homeController"></ng-include> // Navbar
<div ng-view></div> // Angular views
The problems are:
ng-controller cannot be used with resolve since it creates an AngularJs error of 'unknown provider'. Therefore, the ng-include creates trouble for the '/' route.
I cannot/do not know how to specify a resolve for the navbar since it has no route, but is included in every view in index.html. And the navbar needs to show the name of the logged in user.
EDIT1:
I tried an ugly solution, by returning myPromise.$$state.value in homeController and removing the resolve {...}. However, it feels like I shouldn't use the $q promises like this. Any other suggestions?
EDIT2:
What I mean is that the loggedUser is unknown because of ng-controller="". Here is an explanation: AngularJS, resolve and unknown provider.
I think the reason why you get an error about 'unknown provider' is that you need to inject the service userService into the resolve function :
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'partials/home.html',
controller: 'homeController',
resolve: {
loggedUser: function(userService) {
return userService.getLoggedUser();
}
}
}]);
You can separate the navbar from the rest of your app.
Use something like
<body>
<div ng-controller = "navbarController as nav">
<div ng-show=" userIsLoggedIn"> <!-- show navbar only if true -->
<!-- navbar markup-->
</div>
</div>
<div ng-view> <!-- display other templates here --> </div>
</body>
You can then use a service in which us store the login status and credentials of the user. As services can be accessed app wide, you can access its data (like the username) in your navbarController.

Reading URL Query string

I have the following URL:
http://myUrl.com/#/chooseStyle?imgUpload=6_1405794123.jpg
I want to read the imgUpload value in the query string - I'm trying:
alert($location.search().imgUpload);
But nothing alerts, not even a blank alert - but console reads:
$location is not defined
I need this value to add into a controller to pull back data, and also to carry into the view itself as part of a ng-src
Is there anything I'm doing wrong? this is my app config:
capApp.config(function($locationProvider, $routeProvider) {
$locationProvider.html5Mode(false);
$routeProvider
// route for the home page
.when('/', {
templateUrl : '/views/home.html',
controller : 'mainController'
})
// route for the caption it page
.when('/capIt', {
templateUrl : '/views/capIt.html',
controller : 'mainController'
});
}):
This is the view:
<div class="container text-center">
<h1 class="whiteTextShadow text-center top70">Choose your photo</h1>
</div>
<script>
alert($location.search().imgUpload);
</script>
Main controller:
capApp.controller('mainController', function($scope) {
$scope.message = 'Whoop it works!';
});
My end goal is that I can find a solution to capturing and re-using data from the query string.
I will also mention, this is only my first week in Angular, loving it so far! A lot to learn...
<script>
alert($location.search().imgUpload);
</script>
You're making two mistakes here:
executing code while the page is loading, and the angular application is thus not started yet
assuming $location is a global variable. It's not. It's an angular service that must be injected into your controller (or any other angular component). This should cause an exception to be thrown and displayed in your console. Leave your console open always, and don't ignore exception being thrown.
You should not do this
<script>
alert($location.search().imgUpload);
</script>
// you need to inject the module $location
//(either in service, or controller or wherever you want to use it)
// if you want to use their APIs
capApp.controller('mainController', function($scope, $location) {
$scope.message = 'Whoop it works!';
//use API of $location
alert($location.search().imgUpload);
});

function called twice inside angularjs controller

I am new to angular js and currently stuck with very wired kind of a bug. function in a controllers runs twice when its called by view loaded against a route.
http://jsfiddle.net/4gwG3/5/
you will see alert twice!!
my view is simple
and my app code is following
var IB = angular.module('IB', []);
//channel controller
IB.controller('channelsController', function ($scope, $routeParams) {
$scope.greet = function () {
alert('hi');
};
});
IB.config(function ($routeProvider) {
$routeProvider
.when('/channels', {
controller: 'channelsController',
template: '{{greet()}}'
})
.otherwise({ redirectTo: '/channels' });
});
First check that you're not initializing your Angular app twice (by having it initialized automatically with ng-app).
One time I had 2 html pages with ng-app (one for login.html and
another for main.html) and this was a problem I realized later.
Second and for me the most important, check if you have attached your controller to multiple elements. This is a common case if you are using routing.
In my case I was navigating to DashboardController like so:
app.config(function($routeProvider){
$routeProvider
.when('/', {
controller: 'DashboardController',
templateUrl: 'pages/dashboard.html'
})
});
But I also had this in dashboard.html:
<section class="content" ng-controller="DashboardController">
Which was instructing AngularJS to digest my controller twice.
To solve it you have two ways:
removing ng-controller from your html file like this:
<section class="content">
or removing controller from routing (that is normally situated in app.js):
app.config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'pages/dashboard.html'
})
});
I think by creating an interpolation {{greet()}}, you create a watch on function greet. This function can get call as many time as digest cycle runs, so it is not a question about it running 1 or 2 times. So you should not depend upon the times the function is called.
I dont know what you are trying to achieve here. There are two alerts
1. When the controller is called.
2. When the template is get evaluated.
template is to provide the view part, however, in this case template is just evaluating function which is not creating any view.
I had the same problem, so I did:
$scope.init=function()
{
if ($rootScope.shopInit==true) return;
$rootScope.shopInit=true;
...
}
$scope.init();
Like if it were a singleton ! (I had many ajax calls each time I display, it was boring)

How to make controller in angular main layout run on route change?

I have an angular page that has an ng-controller directive and an ng-view directive.
<body ng-controller="MainController">
<h1>Welcome to my main template</h1
<ng-view></ng-view>
</body>
I also have routes configured.
angular.module('app', []).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/', {templateUrl: '/templates/home.html', controller: HomeController}).
when('/start', {templateUrl: '/templates/start.html', controller: StartController});
$locationProvider.html5Mode(true);
}]);
When I click a URL that routes me to /start for example, only StartController runs, not MainController. I guess this kind of makes sense since the main layout has already loaded, and then the template only needs to be loaded now, but there is logic in my MainController that controls part of the template view I need to run.
However, if I refresh the entire page, both controllers run.
Is there any way to make both controllers run? Is this the wrong pattern to follow?
Listen for $routeChangeSuccess on your main controller to get notified when route changes.
app.controller('MainController', function($scope) {
$scope.$on('$routeChangeSuccess', function(event, current, previous, rejection) {
if (current == 'someRoute') {
//execute some route logic
}
});
})
Move the logic from MainController into a service, depend on that service in the individual view-controllers. Then call the service from the view-controllers to get your logic executed.

Resources