app.controller('PageCtrl', ['$scope', '$stateParams', '$state', 'USER_ROLES', 'AuthService', function($scope,$stateParams,$state,USER_ROLES, AuthService){
//console.log("Page Controller reporting for duty.");
$scope.currentUser = null;
$scope.currentUserExists = false; //<- defined in scope of PageCtrl
$scope.userRoles = USER_ROLES;
$scope.isAuthorized = AuthService.isAuthorized;
$scope.setCurrentUser = function (user) {
$scope.currentUser = user;
$scope.currentUserExists = true; //<- set true here!!
};
Now in my html code I'm doing:
<body ng-app="myApp" ng-controller="PageCtrl">
....
<div class="navbar-brand" ng-if="currentUserExists">Welcome!!</div>
<div class="navbar-brand" ng-if="currentUser.data.teacher._id">Welcome2!!</div>
Iv tried ng-show, and I'm trying both examples above to test it.
If i log to console currentUser within my js file everything appears to be working normal. But nothing will show on my page.
Am i missing something??
currentUser is json set like:
$scope.login = function (credentials) {
AuthService.login(credentials).then(function (user) {
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
$scope.setCurrentUser(user);
console.log("currentuser");
console.log($scope.currentUser.data.teacher._id); //Yes its working...
}, function () {
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
});
};
...
authService.login = function (credentials) {
return $http({
method: 'POST',
url: 'proxy2.php',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {
url: 'http://teach.classdojo.com/api/dojoSession?_u=tid',
login: credentials.login,
password: credentials.password,
type: 'teacher'
}
}).success(function (res) {
alert("login success");
Session.create(res.teacher._id, "admin");
return res.teacher;
}).error(function (res) {
alert(res.error.detail);
});
};
You may want to try this:
<div class="navbar-brand" ng-if="currentUserExists==true">Welcome!!</div>
The problem may be due to your setting a primitive value on the scope.
Try using view.currentUserExists instead- so set $scope.view = {currentUserExists: false} in the initialization and then $scope.view.currentUserExists = true in the promise resolution.
I couldn't understand why the scope wasn't working on the page, apparently due to inheritence or maybe because i was using $scope in two controllers?
Anyway i solved it using a service:
$scope.login = function (credentials) {
AuthService.login(credentials).then(function (user) {
userService.setCurrentUser(user); //<----Added this
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
}, function () {
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
});
};
...
var updateUser = function() {
scope.view.currentUser = userService.getCurrentUser();
};
scope.$on(AUTH_EVENTS.loginSuccess, updateUser);
..
app.service('userService', function() {
var currentUser = null;
return {
setCurrentUser: function(user) {
currentUser = user;
},
getCurrentUser: function() {
return currentUser;
}
};
});
Related
I am trying to pre-load data based on ng-controller attributes prior to displaying the html and in turn prior to button click(submit). I am new to angular js and not sure how to accomplish the task.
There will be one question and n number of answer options
May last try is as seen in code but I need to get to the controller other than button click. I need to see the question and possible answers before the html is present.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="http://home-dev.kmhp.com/global/js/AngularJS/angularjs.min.1.7.5.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular-route.min.js"></script>
<script src="http://home-dev.kmhp.com/global/js/AngularJS/quick-survey/app.js"></script>
<script src="http://home-dev.kmhp.com/global/js/AngularJS/quick-survey/Controllers/vote.js"></script>
<!--<script src="http://home-dev.kmhp.com/global/js/AngularJS/quick-survey/Controllers/HomePageVoteController.js"></script>-->
<script src="http://home-dev.kmhp.com/global/js/AngularJS/quick-survey/services/vote.js"></script>
<script src="http://home-dev.kmhp.com/global/js/AngularJS/quick-survey/services/route.js"></script>
<script>
// app
var app = angular.module('quickSurveyApp', ["ngRoute"]);
// controller(s)
app.controller("VoteCtrl", ["$scope", "qa", "$location", function ($scope, qa, $location) {
//app.controller("VoteCtrl", ["$scope", "qa", "$location", function ($scope, qa, $location) {
// app.factory("VoteService", ["$scope", "qa", "$location", function ($scope, qa, $location) {
$scope.activeQuestions = qa.activeQuestions;
$scope.records = qa.records;
$scope.QuestionText = qa[0].QuestionText;
$scope.AnswerText = qa[0].AnswerText;
$scope.Answers = qa[0].Answers;
$scope.error = false;
$scope.AddVote = function () {
$scope.error = !!$scope.answer;
}
}]);
// service(s)
app.factory("VoteService", ["$http", "$q", function ($http, $q) {
res.setHeader('Access-Control-Allow-Origin', '*');
var service = {};
//Gets all data for page.
var questionNumber = 0;
service.pageInit = function () {
var deferred = $q.defer();
$http.get('/API/quick-survey/api/Question/GetQuestionsByZone/0').then(function (response) {
deferred.resolve(response.data);
}, function (error) {
console.error(error);
deferred.reject("error");
});
return deferred.promise;
};
return service;
}]);
// route(s)
app.config(["$routeProvider", function ($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "/api-test-pages/Quick Survey/survey.html",
//controller: "VoteCtrl",
controller: "VoteCtrl",
// it's is good to download the data before displaying the template without the data
// so all we found in resolve is gonna be "resolved" before display the page and running the controller
resolve: {
qa: ["VoteService", "$route", function (VoteService, $route) {
return VoteService.pageInit();
}]
}
}).
otherwise({
redirectTo: '/'
});
}]);
</script>
</head>
<body ng-app="quickSurveyApp">
<div>
<h1>Quick Survey</h1>
<div ng-view></div>
</div>
</body>
</html>
var app = angular.module("quickSurveyApp", ["ng-Route"]);
app.config(["$routeProvider", function ($routeProvider) {
//res.setHeader('Access-Control-Allow-Origin', '*');
$routeProvider
.when("/", {
templateUrl: "/api-test-pages/Quick-Survey/survey.html",
//templateUrl: "/API/quick-survey/api-test-pages/Quick Survey/survey.html",
controller: "VoteCtrl",
resolve: {
qa: ["VoteService", "$route", function (VoteService, $route) {
// return VoteService.pageInit(1);
return VoteService.pageInit();
}]
}
})
.when("/question/:q", {
templateUrl: "templates/survey.tpl",
controller: "VoteCtrl",
resolve: {
qa: ["VoteService", "$route", function (VoteService, $route) {
var questionNumberFromURL = $route.current.params.q;
//return VoteService.pageInit(questionNumberFromURL);
return VoteService.pageInit();
}]
}
})
.when("/thanks", {
templateUrl: "templates/home.tpl",
controller: ["$timeout", "$scope", "$location", function ($timeout, $scope, $location) {
$scope.message = "Thank you !!!";
$timeout(function () {
$location.path("/");
}, 3000);
}]
}).
otherwise({
redirectTo: '/xxxx.html'
});
var app = angular.module('quickSurveyApp', ["ngRoute"]);
function SetCookiesForDebugging() {
var thecookie = "departid=351&jobtitle=Digital+Developer&floor=0&username=ij25405&ps%5Fdeptname=Digital+Experience&ps%5Fdeptid=351&cost%5Fcenter=351&birthday%5Fday=16&birthday=0&fsla= &psdeptname=Digital+Experience&managerwholename=Lawrence+Raffel&area=215&mailstop=%2D+None+Selected+%2D&managerid=21286&departmentid=0&extension=2158635597&emplid=08636&managerusername=LR22638&deptname=KY+Exec+Dir&cubeoffice%5Fno=+&ismanager=0&email=tmruk%40amerihealthcaritas%2Ecom&lob=1&fname=Timothy&is%5Fuserlive=1&psdeptid=351&url=%23&costcenter=351&lname=Mruk&company=KEY&managerphone=2159378142&is%5Fmanager=0&wholename=Timothy+Mruk&id=13332&building=0&guest="
document.cookie = thecookie;
}
// sets all scope variables based on associate cookie information.
function SetUser($scope) {
//Set User Information with Cookie data
$scope.IsManager = getCookie("ismanager");
$scope.UserId = getCookie("emplid"); //
$scope.FirstName = getCookie("fname");
$scope.LastName = getCookie("lname");
$scope.EmailAddress = getCookie("email");
$scope.UserName = getCookie("username");
}
// loops through iNSIGHT cookie to retrieve specific value.
// removes all HTML characters.
function getCookie(name) {
var cookiesArray = document.cookie.split("&");
for (var i = 0; i < cookiesArray.length; i++) {
var nameValueArray = cookiesArray[i].split("=");
var cookieName = decodeURI(nameValueArray[0]);
var cookieValue = nameValueArray[1].replace(/\+/g, '%20');
cookieValue = decodeURIComponent(cookieValue);
if (cookieName == name) {
return decodeURI(cookieValue);
}
}
}
app.controller("VoteCtrl", function ($scope, $http) {
SetCookiesForDebugging();
SetUser($scope);
$scope.voteRequest = {
VoteId: null,
VoteDate: null,
UserName: $scope.UserName,
VoterFname: $scope.FirstName,
VoterLname: $scope.LastName,
Id: null,
QuestionId: null,
QuestionText: "",
AnswerText: ""
};
//Gets all data for page.
$scope.pageInit = function () {
res.setHeader('Access-Control-Allow-Origin', '*');
$http({
method: 'GET',
url: '/API/quick-survey/api/Question/GetQuestionsbyZone/0'
//*url: 'http://localhost:51230/api/Question/GetQuestionsByZone/0'
}).then(function (response){
$scope.activeQuestions = response.data;
},function (error){
console.log(error);
});
};
// inserts new request
$scope.insertRequest = function () {
$http.post("/API/quick-survey/api/Vote/AddVote", $scope.voteRequest).then(function (data, status, headers, config) {
alert("success");
}, function (data, status, headers, config) {
console.log("error!");
console.log(data);
});
};
// checks if user already voted for a question
$scope.getUserVoteCount = function () {
// get true or false
$http.get("/API/quick-survey/api/Vote/GetUserVoteCount/866/ijohnson/0").success(function (data, status, headers, config) {
$scope.activeQuestions = data;
}).error(function (data, status, headers, config) {
console.log(status);
});
};
//radio button click on request form
$scope.handleAnswerRadioClick = function (data) {
$scope.voteRequest.QuestionId = data.QuestionId;
$scope.voteRequest.Id = data.Id;
$scope.voteRequest.AnswerText = data.AnswerText;
};
});
var app = angular.module('quickSurveyApp', ["ngRoute"]);
app.controller("VoteCtrl", ["$scope","qa","$location", function ($scope, qa, $location) {
SetCookiesForDebugging();
SetUser($scope);
$scope.voteRequest = {
VoteId: null,
VoteDate: null,
UserName: $scope.UserName,
VoterFname: $scope.FirstName,
VoterLname: $scope.LastName,
Id: null,
QuestionId: null,
QuestionText: "",
AnswerText: ""
};
$scope.activeQuestions = qa.activeQuestions;
//*******
$scope.Answers = qa.records;
$scope.error = false;
$scope.AddVote = function () {
if ($scope.answer == undefined)
$scope.error = true;
else {
$scope.error = false;
if (qa.next)
$location.path("question/" + qa.next)
else
$location.path("thanks");
}
}
//radio button click on request form
$scope.handleAnswerRadioClick = function (data) {
$scope.voteRequest.QuestionId = data.QuestionId;
$scope.voteRequest.Id = data.Id;
$scope.voteRequest.AnswerText = data.AnswerText;
};
function SetCookiesForDebugging() {
var thecookie = "departid=351&jobtitle=Digital+Developer&floor=0&username=ij25405&ps%5Fdeptname=Digital+Experience&ps%5Fdeptid=351&cost%5Fcenter=351&birthday%5Fday=16&birthday=0&fsla= &psdeptname=Digital+Experience&managerwholename=Lawrence+Raffel&area=215&mailstop=%2D+None+Selected+%2D&managerid=21286&departmentid=0&extension=2158635597&emplid=08636&managerusername=LR22638&deptname=KY+Exec+Dir&cubeoffice%5Fno=+&ismanager=0&email=tmruk%40amerihealthcaritas%2Ecom&lob=1&fname=Timothy&is%5Fuserlive=1&psdeptid=351&url=%23&costcenter=351&lname=Mruk&company=KEY&managerphone=2159378142&is%5Fmanager=0&wholename=Isaac+Johnson&id=22665&building=0&guest="
document.cookie = thecookie;
}
// sets all scope variables based on associate cookie information.
function SetUser($scope) {
//Set User Information with Cookie data
$scope.IsManager = getCookie("ismanager");
$scope.UserId = getCookie("emplid"); //
$scope.FirstName = getCookie("fname");
$scope.LastName = getCookie("lname");
$scope.EmailAddress = getCookie("email");
$scope.UserName = getCookie("username");
}
// loops through iNSIGHT cookie to retrieve specific value.
// removes all HTML characters.
function getCookie(name) {
var cookiesArray = document.cookie.split("&");
for (var i = 0; i < cookiesArray.length; i++) {
var nameValueArray = cookiesArray[i].split("=");
var cookieName = decodeURI(nameValueArray[0]);
var cookieValue = nameValueArray[1].replace(/\+/g, '%20');
cookieValue = decodeURIComponent(cookieValue);
if (cookieName == name) {
return decodeURI(cookieValue);
}
}
}
}]);
app.factory("VoteService", ["$http", "$q", function ($http, $q) {
var service = {};
var urlBase = "API/quick-survey/api";
$scope.pageInit = function () {
// Get Questions from api
res.setHeader('Access-Control-Allow-Origin', '*');
$http({
method: 'GET',
url: '/API/quick-survey/api/Question/GetQuestionsByZone/0'
}).then(function (response) {
$scope.activeQuestions = response.data;
}, function (error) {
console.log(error);
});
};
//Gets all data for page.
service.pageInit = function () {
var deferred = $q.defer();
//res.setHeader('Access-Control-Allow-Origin', '*');
//$http.get(urlBase + '/Question/GetQuestionsByZone/' + questionNumber).then(function (response) {
// $http.get(urlBase + '/Question/GetQuestionsByZone/' + 0).then(function (response) {
$http.get('/API/quick-survey/api/Question/GetQuestionsByZone/0').then(function (response) {
deferred.resolve(response.data);
}, function (error) {
console.error(error);
deferred.reject("error");
});
return deferred.promise;
};
// inserts new request
service.insertRequest = function (questionNumber) {
var deferred = $q.defer();
$http.post(urlBase + '/Vote/AddVote', $scope.voteRequest).then(function (response, status, headers, config) {
console.log(response.data);
deferred.resolve(response.data);
}, function (error) {
console.error(error);
deferred.reject("error");
});
return deferred.promise;
};
// checks if user already voted for a question
service.getUserVoteCount = function (questionNumber) {
var deferred = $q.defer();
// get true or false
$http.get(urlBase + '/Vote/GetUserVoteCount/866/ijohnson/' + questionNumber).success(function (response, status, headers, config) {
deferred.resolve(response.data);
}, function (error) {
console.error(error);
deferred.reject("error");
});
return deferred.promise;
};
return service;
}]);// JavaScript source code
h1>Quick Survey</h1>
<div ng-model="QuestionText">
<!--Question-->
<h2>{{QuestionText}}</h2>
</div>
<!-- <div -->
<div ng-model="AnswerText">
<!--Possible Answers-->
<br ng-repeat-start="a in Answers" />
<input id="button{{a.AnswerText}}" name="selection" value="{{a.AnswerText}}" type="radio" ng-model="$parent.Answer" />
<label for="button{{a.AnswerText}}" ng-repeat-end>{{a.AnswerText}}</label>
</div>
<br />
<br />
<div>
<input id="surveybtn" type="button" value="Vote Now" ng-click="AddVote()" />
</div>
I have an AngularJs application working with components and several modules. I created a plunker example to present my problem here.
I have my NavbarComponent where I declared my Controller where I inject my service called NavbarService.
In the NavbarService, I inject a factory resource to make my Rest call, once this call is made I'm trying to made some treatment on the response before returning it back to the controller, in this example I just apply a simple filter on it, but it doesn't work. If I omit my treatment and return only the categories, the code works and you can visualize a list of two.
I can make my treatment in the controller but this is a bad practice 'cause I believe it should be done in the Service, secondly since it's an asynchronous response I must do something like this to make it work, which is really really ugly:
navbarService.getCategories().$promise.then(function (response) {
console.log("controller", response[0].category);
vm.categories = categoryFilter(response[0].category);
}, function (error) {
console.log("an error occured");
});
Can someone please guide me through this, I'm out of solutions. Thank you
Another simple way is to pass a callback function to service from you component like this
'use strict';
angular.module('navbar').component('appNavbar', {
templateUrl: "navbar.template.html",
controller: [ 'navbarService', function appNavbarController(navbarService) {
var vm = this;
navbarService.getCategories(function(data){
// this will be called when service will get the response and filter function has filtered the response
vm.categories = data;
});
}]
});
Now service should be like this
'use strict';
angular.module('navbar').service('navbarService', ['categoryResourceService', 'categoryFilter', function(categoryResourceService, categoryFilter) {
var vm = this;
vm.getCategories = function(callback) {
categoryResourceService.query(function(response) {
console.log("[NavbarService] response:", response);
callback(categoryFilter(response));
}, function(error) {
console.log("[NavbarService] error:", error);
});
//return vm.categories;
}
}]);
Filter will be like this
'use strict';
angular.module('navbar').filter('category', function() {
return function(categories) {
var categoryIds = ['World'];
var result = [];
angular.forEach(categoryIds, function (categoryId) {
angular.forEach(categories, function (category) {
if (category.name == categoryId) {
console.log("Match");
result.push(category);
}
});
});
return result;
};
});
Your filter should be like this and it should be called in transformResponse in $resource query instead of service, i hope this will help you
'use strict';
angular.module('navbar').filter('category', function() {
return function(categories) {
var categoryIds = ['World'];
var result = [];
angular.forEach(categoryIds, function (categoryId) {
angular.forEach(categories, function (category) {
if (category.name == categoryId) {
console.log("Match");
result.push(category);
}
});
});
return result;
};
});
Your categoryResource.service should be like this
angular.module('shared').factory('categoryResourceService',
['$resource','categoryFilter', function($resource, categoryFilter) {
var provider = "categories.json";
var params = {
id: '#id'
};
return $resource(provider, params, {
query: {
isArray: true,
method: 'GET',
params: {},
transformResponse: function(categories) {
var results = categoryFilter(angular.fromJson(categories));
console.log("[categoryResourceService] filtered response:", results);
return results;
}
}
});
}]);
navbar.service should be like this simply
'use strict';
angular.module('navbar')
.service('navbarService', [ 'categoryResourceService', function (categoryResourceService) {
var vm = this;
vm.getCategories = function(){
vm.categories = categoryResourceService.query(function(response){
console.log("[NavbarService] response:", response);
}, function(error){
console.log("[NavbarService] error:", error);
});
return vm.categories;
}
}]);
And components like this
'use strict';
angular.module('navbar').component('appNavbar', {
templateUrl: "navbar.template.html",
controller: [ 'navbarService', function appNavbarController(navbarService) {
var vm = this;
vm.categories = navbarService.getCategories();
}]
});
I have a sails, node-js application in angular-js and I decided to make some tests for it, especifycally in the backend part, for which I am using Jasmine and ngMockE2E tools, because I want to test it with some real server side data.
Here is a part of the code I want to test:
app.controller('IdentificationCtrl', function($scope, $rootScope, ... , ajax) {
_initController = function() {
$scope.loginData = {};
};
$scope.doLogin = function(form) {
if (form.$valid) {
ajax.sendApiRequest($scope.loginData, "POST", "session/login").then(
function(response) {
//$state.go('app.dashboard');
window.localStorage.setItem("sesion", JSON.stringify(response.data));
$rootScope.userTest = response.data;
},
(function(error) {
console.log("error")
})
);
}
};
_initController();
});
Here is my service.js file, in which I provide the ajax service:
angular.module('common.services', [])
.service('ajax', function($http, $rootScope) {
if (window.location.hostname == "localhost") {
var URL = "http://localhost:1349/";
} else {
var URL = "http://TheRealURL/";
}
this.sendApiRequest = function(data, type, method) {
$rootScope.$broadcast('loading:show')
if (method == "session/login" || method == "session/signup") {
var authorization = "";
} else {
var authorization = JSON.parse(window.localStorage["sesion"]).id;
}
data_ajax = {
url: URL + method,
method: type,
headers: {
'Content-Type': 'text/plain',
'authorization': authorization
}
}
if (type === "GET" || type != "delete") {
data_ajax.params = data;
} else {
data_ajax.data = data;
}
if (window.localStorage['admin-language']) {
data_ajax.headers['accept-language'] = window.localStorage['admin-language'];
} else {
data_ajax.headers['accept-language'] = window.navigator.language.toUpperCase();
}
//The test arrives here perfectly
return $http(data_ajax).success(function(data, status, headers, config) {
//But does not enter here
return data;
$rootScope.$broadcast('loading:hide')
}).error(function(data, status, headers, config) {
//Nor here
return data;
$rootScope.$broadcast('loading:hide')
});
//And finally achieves this point, but without making the http call
}
})
Here is the html where I load Jasmine, ngMocks and the test file:
...
<!-- Testing files -->
<link rel="stylesheet" type="text/css" href="lib/jasmine-core/jasmine.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/jasmine.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/jasmine.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/jasmine-html.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/boot.min.js"></script>
<script type="text/javascript" src="lib/angular-mocks/angular-mocks.js"></script>
<script src="js/TestBackend.js"></script>
...
And here is the above referenced testBackend.js file, in which I intend to make the tests:
describe('FirstCycleController', function() {
beforeEach(module('myApp'));
beforeEach(module('ngMockE2E'));
var $controller;
var $rootScope;
var $httpBackend;
beforeEach(inject(function(_$controller_, _$rootScope_, _$httpBackend_) {
$controller = _$controller_;
$rootScope = _$rootScope_;
$httpBackend = _$httpBackend_;
}));
describe('User login', function() {
it('verifys that a user is correctly logged.', inject(function() {
var $identificationScope = {};
var identificationController = $controller('IdentificationCtrl', { $scope: $identificationScope });
var form = {
$valid: true
}
$identificationScope.loginData = {
email: 'user#test.com',
password: 'usertest'
};
$rootScope.userTest = null;
//pass through everything
$httpBackend.whenGET(/^\w+.*/).passThrough();
$httpBackend.whenPOST(/^\w+.*/).passThrough();
//call the login function simulating a login
$identificationScope.doLogin({ $valid: true });
setTimeout(function() {
expect($rootScope.userTest).not.toBe(null);
}, 150);
}));
});
});
The problem is that when running the testBackend.js test file, it doesn't make any http call. It seems that passThrough() function isn't doing his job correctly.
I faced and corrected the issue of not having defined the passThrough() function, which was because I didn't load the ngMockE2E module(instead of ngMock). But this time Jasmine is working fine and the error is simply that the spec is false:
Error: Expected null not to be null.
Apologies if this issue is already resolved, I couldn't find the solution anywhere.
There is detailed discussion around this on angular github issue
I've got a working $http.POST request in a factory whose job is to get a list object and return it. Simple as that, except the object property I'm returning it to just grows legs and leaves. I'll explain:
just the problem bit for right now, everything else seems to be working fine though
$scope.updateObj = function(num) {
console.log("Obj before:\n" + JSON.stringify($scope.Obj));
$scope.Obj.name = "Obj_" + num;
$scope.Obj.list = myFactory.getList($scope.Obj.name);
window.setTimeout(console.log("Obj after:\n" + JSON.stringify($scope.Obj)), 3000);
};
The console.log before the update displays the object just as defined in myController.js, and the console.log after the update has the correct updated information, but is missing the list property altogether.
I set the the console.log checking Obj after the update on a timeout to see if the request just needed a little more time, but I don't think it's working as intended. I'm thinking it's an asynchronous problem, but I'm still fairly new, and I don't have a good grasp on how to use the $q service.
tld;dr: How do I asynchronously attach response.data from $http to an object property?
myFactory.js
app.factory('myFactory', function($http) {
var service = {};
service.getList = function(name) {
try {
console.log("getting" + name);
var temp = $http({
method: 'POST',
url: 'yourmom.com',
headers: {
'Content-Type': 'application/json'
},
data: {list: name},
cache: true
}).then(
function success(response) {
alert(JSON.stringify(response.data.list)); // <- checks out & is exactly what I expect.
return response.data.list;
},
function error(response) {
throw error(response.status);
}
);
}
catch(err) {
alert(err);
return undefined;
}
};
return service;
});
myController.js
app.controller('GUIcontroller', ['$scope', 'myFactory', 'networkFactory', function($scope, myFactory, networkFactory) {
$scope.number = undefined;
$scope.networkInit = networkFactory.init();
$scope.Obj = {
id: 0,
name: "",
list: {}
};
$scope.updateObj = function(num) {
console.log("Obj before:\n" + JSON.stringify($scope.Obj));
$scope.Obj.name = "Obj_" + num;
$scope.Obj.list = myFactory.getList($scope.Obj.name);
console.log("Obj after:\n" + JSON.stringify($scope.Obj));
};
}]);
You need to think about promises differently. The main benefit of having promises is that you get the result exactly when it's done, whether it's successful or throws an error.
This is a proposed way of doing what you're trying to achieve:
app.factory('myFactory', function($http) {
var service = {};
service.getList = function(name) {
return $http({
method: 'POST',
url: 'yourmom.com',
headers: {
'Content-Type': 'application/json'
},
data: {list: name},
cache: true
});
};
return service;
});
app.controller('GUIcontroller', ['$scope', 'myFactory', 'networkFactory', function($scope, myFactory, networkFactory) {
$scope.number = undefined;
$scope.networkInit = networkFactory.init();
$scope.Obj = {
id: 0,
name: "",
list: {}
};
$scope.updateObj = function(num) {
$scope.Obj.name = "Obj_" + num;
myFactory.getList($scope.Obj.name).then(function(response) {
$scope.Obj.list = response;
}).catch(function(err) {
console.error('Error fetching list: ', err);
});
};
}]);
I have an EmailAccountsController and I need to inject 'Hosting' and 'EmailAccount' services into it. Here is my code:
hostingsModule.controller('EmailAccountsCtrl', ['$scope', 'Hosting', 'EmailAccount', function ($scope, Hosting, EmailAccount) {
var hostingId = 1
$scope.hosting = Hosting.find(hostingId);
$scope.emailAccounts = EmailAccount.all(hostingId)
}]);
The error message is TypeError: Cannot call method 'all' of undefined
When I inject only one service into the same controller, everything works. Is there a way how to inject multiple services into one controller?
EDIT: I've tried to put all the relevant code into one file. It' looks like this:
hostingsModule.factory('Hosting', ['$http', function($http) {
var Hosting = function(data) {
angular.extend(this, data);
};
Hosting.all = function() {
return $http.get('<%= api_url %>/hostings.json').then(function(response) {
return response.data;
});
};
Hosting.find = function(id) {
return $http.get('<%= api_url %>/hostings/' + id + '.json').then(function(response) {
return response.data;
});
}
return Hosting;
}]);
hostingsModule.factory('EmailAccount', ['$http', function($http) {
var EmailAccount = function(data) {
angular.extend(this, data);
};
EmailAccount.all = function(hostingId) {
return $http.get('<%= api_url %>/hostings/' + hostingId + '/email-accounts.json').then(function(response) {
return response.data;
});
};
EmailAccount.find = function(id) {
return $http.get('<%= api_url %>/hostings/' + id + '.json').then(function(response) {
return response.data;
});
};
}]);
hostingsModule.controller('EmailAccountsCtrl', ['$scope', 'Hosting', 'EmailAccount', function($scope, Hosting, EmailAccount) {
var hostingId = 1;
$scope.hosting = Hosting.find(hostingId);
$scope.emailAccounts = EmailAccount.all(hostingId)
console.log($scope.hosting);
console.log($scope.emailAccounts);
}]);
Scope issue. You need to return EmailAccount since it is initialized inside the closure.
You need to add return EmailAccount; like what you did for Hosting.
Or try this code:
hostingsModule.factory('EmailAccount', ['$http', function ($http) {
var service = {
all: function (hostingId) {
return $http.get('<%= api_url %>/hostings/' + hostingId + '/email-accounts.json').then(function (response) {
return response.data;
});
},
find: function (id) {
return $http.get('<%= api_url %>/hostings/' + id + '.json').then(function (response) {
return response.data;
});
}
}
return service;
}]);