Why controller called twice, when state changes? - angularjs

This is my app.js
angular.module('app', ['ui.router', 'satellizer'])
.constant('API_URL', 'http://localhost/angular/public/api/v1/')
.config(function($stateProvider, $urlRouterProvider, $authProvider) {
$authProvider.loginUrl = 'angular/public/api/authenticate';
$urlRouterProvider.otherwise('/auth');
$stateProvider
.state('auth', {
url: '/auth',
templateUrl: 'app/view/login.html',
controller: 'AuthController as auth'
})
.state('dashboard', {
url: '/dashboard',
templateUrl: 'app/view/dashboard.tmpl.html',
params: {
model: ''
}
})
.state('dashboard.employees', {
templateUrl: 'app/view/employee.tmpl.html',
controller: 'employeesController',
}).state('dashboard.test', {
templateUrl: 'app/view/edit.tmpl.html',
controller: 'employeesController',
})
});
When I click ui-sref="dashboard.employees" controller calls twice.
calls twice
This is my controller which I want to use for all views. I developed cms on laravel and angular. I can't create a new controller for every table entity.
angular.module('app')
.controller('employeesController', function($scope, $http, API_URL,$stateParams) {
//retrieve employees listing from API
$scope.employees = '';
$http.get(API_URL + $stateParams.model)
.success(function(response) {
$scope.employees = response;
});
//show modal form
$scope.toggle = function(modalstate, id) {
$scope.modalstate = modalstate;
switch (modalstate) {
case 'add':
$scope.form_title = "Add New Employee";
break;
case 'edit':
$scope.form_title = "Employee Detail";
$scope.id = id;
$http.get(API_URL + $stateParams.model+'/' + id)
.success(function(response) {
console.log(response);
$scope.employee = response;
});
break;
default:
break;
}
$('#myModal').modal('show');
}
//save new record / update existing record
$scope.save = function(modalstate, id) {
var url = API_URL + "employees";
//append employee id to the URL if the form is in edit mode
if (modalstate === 'edit') {
url += "/" + id;
}
console.log('saved');
$http({
method: 'POST',
url: url,
data: $.param($scope.employee),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function(response) {
var index = _.findIndex($scope.employees, function(b) {
return b.id == $scope.employee.id;
});
console.log(index);
if (index != -1) {
$scope.employees[index] = $scope.employee;
} else {
console.log($scope.employee);
$scope.employee.id = response;
$scope.employees.push($scope.employee);
console.log($scope.employees);
}
$('#myModal').modal('toggle');
}).error(function(response) {
console.log(response);
alert('This is embarassing. An error has occured. Please check the log for details');
});
}
//delete record
$scope.confirmDelete = function(employee) {
var isConfirmDelete = confirm('Are you sure you want this record?');
if (isConfirmDelete) {
$http({
method: 'DELETE',
url: API_URL + 'employees/' + employee.id
}).
success(function(data) {
_.remove($scope.employees, function(n) {
return n.id == employee.id;
});
console.log(data);
}).
error(function(data) {
console.log(data);
alert('Unable to delete');
});
} else {
return false;
}
}
});
Where is my mistake? How can I fix that?

kindly check, if you are called the controller in your employee.tmpl.html page, like ng-controller="employeesController"
Please remove it, if you call the ng-controller in your html

Related

separated controller from component

Component:
crudModule.js
var crudModule = angular.module('crudModule', ['ui.router', 'smart-table', 'ngCookies', 'ui.bootstrap', 'angularModalService', 'dialogs', 'remoteValidation']);
angular.module('crudModule').component('applicationInfo', {
templateUrl: 'infoApplication.html',
controller: 'applicationInfoCtrl'
});
applicationInfoCtrl.js:
var crudModule = angular.module('crudModule')
crudModule.controller('applicationInfoCtrl', ['httpService', '$scope', function($http, $scope, $cookies, $stateParams, httpService) {
httpService.httpGetRequest("http://localhost:8080/applications/" + $stateParams.id).then(function success(response) {
$scope.application = response.data;
});
$scope.getApiKey = function () {
httpService.httpGetRequest('http://localhost:8080/applications/generateApiKey').then(function success(response) {
$scope.application.apikey = response.data.apikey;
$scope.application.apisecret = response.data.apisecret
})
};
$scope.send = function (object, url) {
httpService.httpPostRequest(object, url + "/" + $stateParams.id).catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
}).then(function success(response){
});
}
}]);
httpService.js:
var crudModule = angular.module('crudModule')
crudModule.factory('httpService', function($http) {
return {
httpGetRequest: function (url) {
return $http({
method: 'GET',
url: url
})
},
httpPostRequest: function (object, url){
return $http({
method:'POST',
url: url,
data: object
})
}
}
});
I am getting error:
Cannot read property 'httpGetRequest' of undefined.
I have injected my httpService and i dont find any mistakes yet
The problem is the order of parameters in your controller, it should be
crudModule.controller('applicationInfoCtrl', ['$http','httpService', '$scope','$cookies','$stateParams' function(http,httpService, $scope,$cookies,$stateParams) {
}

How to get specific state in AngularJS by local-storage?

I want to change state by local-storage in my application after page refresh. How to get the state?.
HTML:
<body ng-app="sampleApp">
<div class="container" ng-controller="Registration" ng-init ="temp()">
<div ui-view></div>
</div>
Controller:
var sampleApp = angular.module('sampleApp',
['ui.router','angularFileUpload','ngStorage']);
sampleApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('settings', {
url: '/settings',
templateUrl: '/ui/step1.htm'
.state('settings/Personal_Info', {
url: '/Personal_Info',
templateUrl: '/ui/step2.htm',
//controller: 'ProfileController'
})
.state('settings/Personal_Info_1', {
url: '/Personal_Info_1',
templateUrl: '/ui/step3.htm',
//controller: 'AccountController'
})
.state('settings/P_Info_Affiliations', {
url: '/P_Info_Affiliations',
templateUrl: '/ui/step4.htm',
//controller: 'ProfileController'
});
$urlRouterProvider.otherwise('/settings');
});
sampleApp.controller("Registration",
function ($scope, $location, $http, $state, $localStorage){
$scope.currentstep = 1;
$scope.formData = {};
$scope.temp = function()
{ alert($localStorage.currentstep);
if($localStorage.currentstep > 0) {
$scope.currentstep = $localStorage.currentstep;
$scope.getStepUrl();
}
}
$scope.next = function(formData){
console.log($scope.currentstep);
//console.log($scope.formData);
if (formData.check == 1) {
$scope.currentstep = $scope.currentstep + 1;
$localStorage.currentstep = $scope.currentstep;
alert("Everything is validated. We can go ahead");
$http({
method : 'POST',
url : 'addstep?step'+ $scope.currentstep,
data : $scope.formData,
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function(data) {
if (data.errors) {
$scope.errorName = data.errors.name;
$scope.errorUserName = data.errors.username;
$scope.errorEmail = data.errors.email;
} else {
$scope.message = data.message;
}
});
$scope.getStepUrl();
}
else {
alert("Some issues in input data.");
}
}
$scope.getStepUrl = function() {
if($scope.currentstep == 1){
$state.go('settings');
}
else if($scope.currentstep == 2){
$state.go('settings/Personal_Info');
alert("i am step 2");
}
else if($scope.currentstep == 3){
$state.go('settings/Personal_Info_1');
}
}
});
I am not geting state properly.
how to solve this issue?
Thank you for your help in advance.
You can get the current state via $state provider and state.current.name
So you can ask for current state in each controller or service you would like to use
Remove the default state
$urlRouterProvider.otherwise('/settings');
Use the else statment in a function
if($localStorage.currentstep > 0) {
$scope.currentstep = $localStorage.currentstep;
$scope.getStepUrl();
}else{
$state.go('settings');
}

how to load more than one service in $state resolve?

I want to load two APIs before page is going to load For it i have used the following code in $stateProvider
.state('admin-panel.default.jobadd', {
url: '/jobadd/:jobID',
templateUrl: 'app/search/jobadd.tmpl.html',
controller: 'JobaddController',
resolve: {
jobAdd: ['Search', '$stateParams','$q', function(Search,$stateParams,$q) { //Search is service
var jobAdd = Search.jobAdd($stateParams.jobID);
var isApplied = Search.is_job_applied($stateParams.jobID);
jobAdd.$promise.then(function(response) {console.log('Resource 1 data loaded!')});
isApplied.$promise.then(function(response) {console.log('Resource 2 data loaded!')});
return $q.all([jobAdd.$promise, isApplied.$promise]);
}]
},
data: {
requireLogin: true
}
});
})
But it's not give the data when injects to the controller, page seems as blank
my controller code is
.controller('JobaddController', function ($scope, $mdDialog, $state, jobAdd, Profile) {
$scope.jobs = jobAdd[0];
$scope.benifits = jobAdd[0].benifits;
if($scope.jobs.short_listed == 1)
$scope.jobs.flag = true;
else
$scope.jobs.flag = false;
$scope.checkShortList= function(job){
if(job.flag){
Profile.rmShortList(job.short_list_id);
job.flag = false;
}
else{
if(job.short_list_id === null){
Profile.addNewShortList(job.id).then(function(response){
job.short_list_id = response.short_list_id;
});
}
else
Profile.addShortList(job.short_list_id,job.id);
job.flag = true;
}
};
$scope.companyModal = function(ev) {
$mdDialog.show({
controller: 'CompanyDetailsController',
templateUrl: 'app/search/company-details.tmpl.html',
parent: angular.element(document.body),
targetEvent: ev,
})
.then(function(answer) {
$scope.alert = 'You said the information was "' + answer + '".';
}, function() {
$scope.alert = 'You cancelled the dialog.';
});
};
$scope.applyModal = function(ev) {
$mdDialog.show({
controller: 'ApplyController',
templateUrl: 'app/search/apply.tmpl.html',
locals: { Jobid: $scope.jobs.id },
parent: angular.element(document.body),
targetEvent: ev,
resolve: {
shortProfile: ['Profile', function(Profile) {
return Profile.shortProfile();
}]
},
})
.then(function(answer) {
$scope.alert = 'You said the information was "' + answer + '".';
}, function() {
$scope.alert = 'You cancelled the dialog.';
});
};
var container = angular.element(document.getElementById('container'));
var section2 = angular.element(document.getElementById('section-2'));
$scope.toTheTop = function() {
container.scrollTop(0, 5000);
};
$scope.toSection2 = function() {
container.scrollTo(section2, 0, 1000);
};
})
in service code
.service('Search', [ '$http', '$q', 'API',
function($http, $q, API) {
var data = '';
this.jobAdd = function(job_id) {
var def = $q.defer();
$http({
url: API.url+'get_job_add_detail?job_id=' + job_id,
method: "GET"
}).success(function(response) {
if(response.status == 'Success'){
data = response.data;
def.resolve(data);
}
}).error(function(response) {
console.log (response);
if(response.status == 'Failed'){
data = response.msg;
def.reject(data);
}
});
return def.promise;
}
this.isJobApplied = function(job_id) {
var def = $q.defer();
$http({
url: API.url+'is_job_applied?job_id='+job_id,
method: "GET",
}).success(function(response) {
if(response.status == 'Success'){
data = response.data;
def.resolve(data);
}
}).error(function(response) {
console.log (response);
if(response.status == 'Failed'){
data = response.msg;
def.reject(data);
}
});
return def.promise;
}
}]);
What's the wrong here?? how to attach more than on service in $state resolve?
simply you can for more than one service.
resolve: {
jobAdd: ['Search', '$stateParams', function(Search,$stateParams) {
return Search.jobAdd($stateParams.jobID);
}],
isApplied: ['Search', '$stateParams', function(Search,$stateParams) {
return Search.isJobApplied($stateParams.jobID);
}]
}

Angular bindings not updating within $interval and $http

I've tried different variations of $apply() and $digest() to no avail.
The binding should update once the courier is no longer null with the name of the courier, however nothing is happening. I've been able to log the name of the courier when they are assigned, however the dom element is not updating. I'm using jade and compiling to html without any issues elsewhere in the application. I'm also calling the refreshDelivery function immediately prior to rendering the view shown below, which is working correctly.
app.js:
var storeController = require('./controllers/controller');
var storeApp = angular.module('AngularStore', ['ngRoute']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/store', {
templateUrl: 'views/store.html',
controller: storeController }).
when('/products/:productSku', {
templateUrl: 'views/product.html',
controller: storeController }).
when('/cart', {
templateUrl: 'views/shoppingCart.html',
controller: storeController }).
when('/delivery', {
templateUrl: 'views/delivery.html',
controller: storeController }).
otherwise({
redirectTo: '/store' });
}])
.controller('storeController', storeController);
controller.js:
function storeController($scope, $routeParams, $http, $interval, DataService) {
// get store and cart from service
$scope.store = DataService.store;
$scope.cart = DataService.cart;
$scope.mapInit = DataService.mapInit;
// use routing to pick the selected product
if ($routeParams.productSku != null) {
$scope.product = $scope.store.getProduct($routeParams.productSku);
}
// var locationOptions = {
// enableHighAccuracy: true,
// timeout: 5000,
// maximumAge: 0
// }
// navigator.geolocation.getCurrentPosition(function(pos){
// var mapOptions = {
// center: { lat: pos.coords.latitude, lng: pos.coords.longitude},
// zoom: 13
// };
// var map = new google.maps.Map(document.getElementById('map'),
// mapOptions);
// });
$scope.search = function(query){
var responseObject;
console.log('in search');
$http({
url:'/apiCall',
data: {data: '/products?keyword=' + query + '&latlong=36.125962,-115.211263'},
method: 'POST'
})
.then(function(response){
responseObject = response.data.data;
responseObject.forEach(function(data){
var productData = {
sku: data.Id.SkuPartNumber,
productName: data.Description.Name,
desc: data.Description.BrandName,
price: data.Price.DisplayPrice,
url: data.Description.ImageURL,
storeNumber: data.StoreNumber
}
var temp = new product(productData)
$scope.store.addProduct(temp)
});
});
}
$scope.getDeliveryQuote = function(){
var responseObject;
$scope.quoted = false;
var storeNumber = $scope.cart.items[0].storeNumber
console.log($scope.cart.items[0].storeNumber);
var url = '/delivery_quote?drop_off_latlong=36.125962,-115.211263&pickup_store_number='.concat(storeNumber);
$http({
url: '/apiCall/',
data: {data: url},
method: 'POST'
})
.then(function(response){
$scope.quoted = true;
console.log(response.data.id);
$scope.quote = response.data.fee;
$scope.quoteId = response.data.id
})
}
$scope.submitOrder = function(){
var url = '/submit_delivery?drop_off_latlong=36.125962,-115.211263&pickup_store_number=0001709&manifest=puppies&phone_number=555-555-5555&quote_id=' + $scope.quoteId + '&customer_name=Arnold';
$http({
url: '/apiCall/',
data: {data: url},
method: 'POST'
})
.then(function(response){
console.log(response);
$scope.deliveryId = response.data.id;
$scope.refreshDelivery();
window.location.href='/#/delivery';
})
}
$scope.refreshDelivery = function() {
var url = '/update?delivery_id='.concat($scope.deliveryId);
var promise = $interval(function(){
$http({
url: '/apiCall/',
data: {data: url},
method: 'POST'
})
.then(function(resp) {
$scope.update = resp.data;
if (resp.data.courier){
$scope.update.courier = resp.data.courier;
console.log($scope.update.courier.name);//outputs correct name
$scope.$apply();
}
//stops when complete
if ($scope.update.complete){
$interval.cancel(promise);
}
})
}, 5000 );
}
}
module.exports = storeController;
Jade before compiling to HTML:
Partial:
p.text-info {{update.courier.name}} is on their way!
Default:
html(ng-app='AngularStore')
head
// includes for jquery, angular, and bootstrap
script(src="https://maps.googleapis.com/maps/api/js?sensor=false")
script(src='bower_components/jquery/dist/jquery.min.js')
script(rel='stylesheet' href='bower_components/bootstrap/dist/css/bootstrap.min.css')
script(src='bower_components/angular/angular.js')
script(src='bower_components/angular-route/angular-route.js')
// includes for the Angular Store app
script(src='/js/main.js')
script(src='/js/bundle.js')
link(href='/styles/main.css', rel='stylesheet', type='text/css')
|
body
.container-fluid
.row-fluid
.span10.offset1
h1.well
a(href='default.html')
| Angular Store
div(ng-view='')
I found a way around the $scope issue by creating a separate controller to handle updates.
app:
var storeController = require('./controllers/storeController'),
deliveryController = require('./controllers/deliveryController');
var storeApp = angular.module('AngularStore', ['ngRoute']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/store', {
templateUrl: 'views/store.html',
controller: storeController }).
when('/products/:productSku', {
templateUrl: 'views/product.html',
controller: storeController }).
when('/cart', {
templateUrl: 'views/shoppingCart.html',
controller: storeController }).
when('/delivery/:id', {
templateUrl: 'views/delivery.html',
controller: deliveryController }).
otherwise({
redirectTo: '/store' });
}])
.controller('storeController', storeController);
new deliveryController
function deliveryController($scope, $routeParams, $http, $interval) {
console.log($routeParams);
var refreshDelivery = function(id) {
var url = '/update?delivery_id='.concat(id);
var promise = $interval(function(){
$http({
url: '/apiCall/',
data: {data: url},
method: 'POST'
})
.then(function(resp) {
$scope.update = resp.data;
if (resp.data.courier){
$scope.update.courier = resp.data.courier;
console.log($scope.update.courier.name);//outputs correct name
}
//stops when complete
if ($scope.update.complete){
$interval.cancel(promise);
}
})
}, 5000 );
}
refreshDelivery($routeParams.id);
}
module.exports = deliveryController;

angular $scope data will not changed

My problem is that I have a $scope.page on to different controllers under the same module.
the $scope.page data should change for each route.
I'm trying to understand this...
some code:
hall.config(function ($routeProvider) {
$routeProvider.when("/", { controller: 'pageForsideController', templateUrl: "pages/forside.html" })
.when("/om", { controller: 'pageOmController', templateUrl: "pages/omMig.html" })
.otherwise({ redirectTo: '/' })
});
hall.controller('pageOmController', function ($scope, siteData) {
siteData.getServices(function (data) {
$scope.services = data;
})
siteData.getPageByName("Mig", function (data) {
$scope.page = data;
});
});
hall.controller('pageForsideController', function ($scope, siteData) {
siteData.getPageByName("Forside", function (data) {
$scope.page = data;
});
});
hall.factory("siteData", function ($http) {
return {
getServices: function (successcb) {
$http({ method: 'GET', url: 'data.json' })
.success(function (data, status, headers, confic) {
successcb(data.services);
console.log("getServices")
});
},
getPageByName: function (name, successcb) {
$http({ method: 'GET', url: 'data.json' })
.success(function (data, status, headers, confic) {
for (var i = 0; i < data.pages.length; i++)
if (data.pages[i].title == name)
successcb(data.pages[i]);
});
}
}
});
Updated:
here is a plunker
http://plnkr.co/edit/9K3C3ahi5WMPeKLeL318?p=preview
The OP fixed the problem by following charlieftl's instructions, and removing the controller from either markup or $routeProvider.

Resources