factory is unable to convey data to another controller - angularjs

I am building a spa with angular and slim framework. As per the bellow mentioned code, what i am trying to do is, login page controller will pass data to landing page controller upon successful submission of user/psw. When i place the factory outside the http call/ log in function it gets the data but on the landing page factory does not deliver the data. And when i place it inside it stops to work. Please help me....
this factory is for sharing data across controllers
appDls.factory('sharedFactory', function () {
var dataTobeShared = {};
var interface = {};
interface.add = function (d) {
dataTobeShared = d;
}
interface.put = function () {
return dataTobeShared;
}
return interface;
});
this controller is for the main portal user redirection and portal rendering
appDls.controller('DlsappController', ['$scope', '$state', 'multipartForm', 'sharedFactory', '$window', function ($scope, $state, multipartForm, sharedFactory, $window) {
$scope.Userdata = [];
$scope.login = function () {
var url = "../scripts/routes.php/authen";
multipartForm.post(url, $scope.login).then(function (d) {
$scope.Userdata.push(d.data[0]);
sharedFactory.add($scope.Userdata);
$window.location.href = '../portal/landing.php';
});
}
}]);
this controller is for landing page routing
appDls.controller('landingController', ['$scope', '$state', 'multipartForm', 'sharedFactory', function ($scope, $state, multipartForm, sharedFactory) {
$scope.UserInfo = sharedFactory.put();
$scope.$watch('UserInfo', function (newValue, oldValue) {
/*here we can use the user data from login page*/
if (newValue.length == 1) {
alert(newValue[0].fullname);
$state.go(newValue[0].proftype);
} else {
alert("user not logged in successfully!");
$state.go('default');
}
}, true);
}]);

When you do sharedFactory.add($scope.Userdata); your $scope.Userdata is another object, which is not watched by landingController. By reassigning dataToBeShared in sharedFactory.add function, you lose the reference to original object, so it is not reachable anymore from code.
To make landingController see the changes you need either to reimplement sharedFactory.add function to push values in sharedFactory.dataTobeShared array or use some event-based notification, not $watch.
Here is the jsfiddle to illustrate my words.

appDls.factory('sharedFactory', function () {
var dataTobeShared = {};
return
{
add: function (d) {
dataTobeShared = d;
}
put: function () {
return dataTobeShared;
}
}
});
appDls.controller('DlsappController', ['$scope', '$state', 'multipartForm', 'sharedFactory', '$window', function ($scope, $state, multipartForm, sharedFactory, $window) {
$scope.Userdata = [];
$scope.$watch('login',function () {
var url = "../scripts/routes.php/authen";
multipartForm.post(url, $scope.login).then(function (d) {
$scope.Userdata.push(d.data[0]);
sharedFactory.add($scope.Userdata);
$window.location.href = '../portal/landing.php';
});
}
}]);
appDls.controller('landingController', ['$scope', '$state', 'multipartForm', 'sharedFactory', function ($scope, $state, multipartForm, sharedFactory) {
$scope.UserInfo = sharedFactory.put();
$scope.$watch('UserInfo', function (newValue, oldValue) {
/*here we can use the user data from login page*/
if (newValue.length == 1) {
alert(newValue[0].fullname);
$state.go(newValue[0].proftype);
} else {
alert("user not logged in successfully!");
$state.go('default');
}
}, true);
}]);

The watcher needs to fetch the value from the factory on each digest cycle, and update the $scope variable.
appDls.controller('landingController', ['$scope', '$state', 'multipartForm', 'sharedFactory', function ($scope, $state, multipartForm, sharedFactory) {
//$scope.UserInfo = sharedFactory.put();
//$scope.$watch('UserInfo', function (newValue, oldValue) {
$scope.$watch(sharedFactory.put, function (newValue, oldValue) {
//UPDATE scope variable
$scope.UserInfo = newValue;
/*here we can use the user data from login page*/
if (newValue.length == 1) {
alert(newValue[0].fullname);
$state.go(newValue[0].proftype);
} else {
alert("user not logged in successfully!");
$state.go('default');
}
}, true);
}]);
The original code only set the scope variable once upon initialization of the controller. It needs to fetch the value from the factory on each digest cycle.

Related

AngularJS stuck in module

app.controller('TableContent', ['$http', '$scope', '$window',
function ($scope, $window) {
console.log("I'm in TableContent");
$scope.EditSaverCommit = function () {
console.log("I'm in EditSaverCommit");
EditIndex = $scope.$index;
EditProjectID = $scope.project.ID;
console.log("Scope has"+$scope.project.Name);
EditProject = $scope.project.Name;
console.log("EditProject has "+EditProject);
};
$scope.DeleteProjectCommit = function () {
console.log("I'm in DeleteProjectCommit");
$window.Project.splice($scope.$index, 1);
ProjectLength = Project.length;
PostData = "";
$scope.Project = $window.Project;
PostData = $scope.Project.ID;
$http.get("https://localhost:44377/project/DeleteProject/"+PostData).then(function (response) {
console.log("I'm in DeleteProject");
$window.Project = response.data;
});
PostData = "";
console.log("I'm not in TableContent");
};
}]);
Hello all, I've had an issue with this snippet when it comes to loading my page.
After the entire page loads, all of my other http.get requests are down ever since I modified this part to accept http.get.
It doesn't print the "I'm not in TableContent" after full load and all other http.get requests are paralyzed but do print their respective console.log() messages.
Parameter $http is missing as function argument:
app.controller('TableContent', ['$http', '$scope', '$window',
function ($http, $scope, $window) {
...
};
}]);
This cracks the dependency injection...

Passing data between angularjs modues/controllers

So I have two modules each one with one with its own controller and I need to pass an object between them, I seen this can be done with a service, I tried some stuff but I keep getting an "$injector" error in the second module/controller. Please help fix this.
This is my first module/controller with its service:
var appIndex = angular.module("AppIndex", ['datatables', 'datatables.bootstrap', 'ui.select']);
appIndex.service('sharedData', function () {
this.data = {};
this.setData = function (newData) {
this.data = newData;
return this.data;
};
this.getData = function () {
return this.data;
};
});
appIndex.controller("IndexController", function ($scope, $http, $window, sharedData) {
sharedData.setData($scope.referencia);
});
And this is my second module/controller:
var appCna = angular.module("AppCna", ['ui.select', 'AppIndex']);
appCna.controller("CnaController", function ($scope, $http, $window, sharedData) {
$scope.referencia = sharedData.getData();
});
You need to call setData in your first controller
appIndex.controller("IndexController", function ($scope, $http, $window, sharedData) {
sharedData.setData($scope.referencia);
});
So in the end I finally stop trying to use a service to my purpose of passing an object between two modules and what I did was to use the LocalStorage function.

angularjs using $on and $broadcast to communicate between a master controller to another controller

I am trying to set communication between two angular controllers (service is not an option). and I am failing desperately.
here is some of my code...
i tried using both $emit and $broadcast
invoiceApp.controller('masterReportConrtoller', ['$scope', '$location', 'authService', 'usSpinnerService', 'dateService', 'settingsService','$rootScope',
function ($scope, $location, authService, usSpinnerService, dateService, settingsService, $rootScope )
////Is User Valid
////
//$rootScope.$on("masterReportConrtoller", function () {
// $scope.parentmethod();
// });
//$scope.parentmethod = function () {
// //
$scope.masterReportConrtoller.getUserDetails = function () {
debugger;
settingsService.getUserDetails().then(function (response) {
var loginData = {
userName: response.d.user.Email,
password: response.d.user.UserPassword
};
authService.login(loginData).then(function (response) {
debugger;
$scope.Limit = response.d.organization.Limit;
});
$scope.Limit = response.d.organization.Limit;
$scope.DocumentUsage = response.d.organization.DocumentUsage;
$scope.ExpirationDate = $scope.DateConvertfromJson(response.d.organization.ExpirationDate);
var fullDate = new Date();
if (fullDate <= $scope.ExpirationDate) {
$scope.ISvalidUser = false;
$rootScope.$broadcast('masterReportConrtoller', false);
}
else {
$rootScope.$broadcast('masterReportConrtoller', true);
}
});
}
}]);
invoiceApp.controller('InvoiceController', ['$scope', '$location', '$cookieStore', 'documentService', 'dialogs', 'usSpinnerService', 'settingsService', 'associatedEmailsService', '$rootScope',
function ($scope, $location, $cookieStore, documentService, dialogs, usSpinnerService, settingsService, associatedEmailsService, $rootScope) {
$rootScope.$on('masterReportConrtoller');}
Based on your parent - child controller relationship, you can use $scope.$broadcast and $scope.$on in your code.
Try something like this:
//masterReportConrtoller
$scope.$broadcast("myCustomEvent", { isValidUser: false });
//InvoiceController
$scope.$on("myCustomEvent" , function(event, data){
//do something with data
});
Please note that this will work if masterReportConrtoller is the parent controller and InvoiceController is the child controller. If this is not the case, then use $rootScope.$broadcast and $rootScope.$on.
You can find more details here.
You can use $localStorage , $stateParams or $cookies or even ... I generally prefer $stateParams to send values and object to states and controller.
$state.go('state2', { someParam : 'broken magic' });
read file using $stateParams from controller . Details can be found here

AngularJS - How to authenticate in first submission?

I have a login function in Angularjs, it works only when I submit it the second time. How to resolve it?
This is the code:
.controller('LoginCtrl',
['$scope', '$rootScope', '$location', 'AuthenticationService',
function ($scope, $rootScope, $location, AuthenticationService) {
// reset login status
AuthenticationService.ClearCredentials();
$scope.login = function () {
$scope.dataLoading = true;
console.log('Entra '+$scope.username);
AuthenticationService.Login($scope.username, $scope.password, function(response) {
if(response.success) {
AuthenticationService.SetCredentials($scope.username, $scope.password, $rootScope.datos.grupo);
$location.path('/');
console.log('Comprueba y redirecciona');
} else {
console.log('Falla');
$scope.error = response.message;
$scope.dataLoading = false;
}
});
};
}]);
I need to make a $scope.$apply() right after changed the location and call replace() to let Angular know that things have changed.
Thank you.

Issue with Angular.js and Angular Style Guide

I'm having an issue correctly getting a data service to work as I try to follow the Angular Style Guide (https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#data-services)
I'm sure it's something obvious to the more experienced but I can't get the data set to assign properly to the vm.items outside of the
Data Service
(function() {
'use strict';
angular
.module('portfolioApp')
.factory('portfolioService', portfolioService);
portfolioService.$inject = ['$http', 'logger'];
function portfolioService($http, logger) {
return {
getPortfolioData: getPortfolioData,
};
function getPortfolioData() {
return $http.get('./assets/portfolio/portfolioItems.json')
.then(getPortfolioDataComplete)
.catch(getPortfolioDataFail);
function getPortfolioDataComplete(response) {
return response.data;
}
function getPortfolioDataFail(error) {
logger.error('XHR Failed for getPortfolioData.' + error.data);
}
}
}
}());
Controller
.controller('portfolioController', ['$scope', '$http', '$stateParams', 'logger', 'portfolioService', function($scope, $http, $stateParams, logger, portfolioService) {
var vm = this;
vm.items = [];
activate();
function activate() {
return getData().then(function() {
logger.info('Activate the portfolio view');
});
}
function getData() {
return portfolioService.getPortfolioData()
.then(function(data) {
vm.items = data;
return vm.items;
});
}
console.log("test")
console.log(vm.items);
console.log("test")
}])
Your getData function is a promise, so it's run asynchronously. Your console.log are called before the end of the promise so the vm.items is still empty.
Try to put the log in the then callback.

Resources