Cordova onloading with factory data - javascript

I'm trying to implement a display of loading message while data is being retrieved. In the case of basic js functions, it works, but in case of using factory to retrieve data, i dont get anything displayed before the data.
example of partial :
<div Class='' ng-controller="contentsCtrl">
<div ng-show="contents.news.length" class="">
<div ng-show="isloading"><br><img src="img/loader.gif" alt="" align='center'><br><br></div>
<ul id="tournois-list" ng-show="!isloading">
<li ng-repeat="content in contents.news track by $index">
<div class="tournois ">
<div class='row'>
<span class='contents_title'>{{content.content_title}}</span>
</div>
<div class='row'>
<span class='contents_dates'>{{content.content_date | date:'dd-MMMM-YYYY'}}</span>
</div>
<div class='row'>
<span class='contents_intro'>{{content.content_intro | htmlToPlaintext}}</span>
</div>
</div>
</li>
</ul>
</div>
</div>
code for controller + factory
baclyApp.controller('contentsCtrl',function($scope,contents){
$scope.isloading=true;
$scope.contents=contents.list();
console.log($scope.contents);
$scope.isloading=false;
})
baclyApp.factory("contents",function($http,$cookies){
var urlphp="http://bacly.fr/baclymphp/";
var contents={};
$http.get(urlphp+"getContent.php").then(function(response)
{
contents.news = response.data;
})
return {
list: function(){
return contents;
}
}
})
I guess this is about the timing as controller inject the factory object, so it needs to be resolved or something like this, but i don't know how to do it on another way.
Thanks !
Update : Here the other controller i'm talking about with multiple get
baclyApp.factory("tournois",function($http,$q){
//Factory qui recupère les données de tournois et iscriptions
// var urlphp="http://localhost/cordova/mbacly/www/php/";
var tournois={};
var urlphp="http://bacly.fr/baclymphp/";
$http.get(urlphp+"getTournois.php").then(function(response)
{
tournois.tournois = response.data;
console.log(tournois);
},function(status) {
alert("pas d acces réseau")
})
$http.get(urlphp+"getTournoinscriptions.php").then(function(response)
{
tournois.inscriptions = response.data;
},function() {
alert("pas d acces réseau")
});
$http.get(urlphp+"getTournoinscris.php").then(function(response)
{
tournois.inscris = response.data;
},function() {
alert("pas d acces réseau")
});
$http.get(urlphp+"getUsers.php").then(function(response)
{
tournois.users = response.data;
},function() {
alert("pas d acces réseau")
});
return {
list: function(){
return tournois;
},
find: function(cid){
return _.find(tournois.tournois, function(t) {return t.tournois_id === cid});
},
findinscris: function(cid){
return _.filter(tournois.inscris, function(t) {return t.tournois_id == cid});
},
findusers: function(uid){
return _.filter(tournois.users, function(t) {return t.user_id === uid});
},
findusersbyname: function(name){
return _.filter(tournois.users, function(t) {return t.uname === name});
},
updateinscription: function($params){
// var urlphp="http://localhost/cordova/mbacly/www/php/";
var urlphp="http://bacly.fr/baclymphp/";
var tournois={};
var retour="retour-OK";
$params_encoded =encodeURIComponent(JSON.stringify($params));
$http.get(urlphp+"saveinscription.php?data="+$params_encoded).success(function(data){
// console.log("retour-OK"+data);
retour="retour-OK";
});
return retour;
},
insertinscription: function($params){
// var urlphp="http://localhost/cordova/mbacly/www/php/";
var urlphp="http://bacly.fr/baclymphp/";
var tournois={};
var retour="retour-OK";
$params_encoded =encodeURIComponent(JSON.stringify($params));
$http.get(urlphp+"saveinscription.php?data="+$params_encoded).success(function(data){
// console.log("retour-OK"+data);
retour="retour-OK";
});
return retour;
},
deleteinscription: function($params){
// var urlphp="http://localhost/cordova/mbacly/www/php/";
var urlphp="http://bacly.fr/baclymphp/";
var tournois={};
var retour="retour-OK";
$params_encoded =encodeURIComponent(JSON.stringify($params));
$http.get(urlphp+"saveinscription.php?data="+$params_encoded).success(function(data){
// console.log("retour-OK"+data);
retour="retour-OK";
});
return retour;
}
}
})
Controller (part of):
baclyApp.controller('tournoisCtrl',['$scope','tournois','$cookies','$state','$window','growl',function($scope,tournois,$cookies,$state,$window,growl){
//Liste des tournois
$scope.showtournoislist=true;
$scope.tournois=tournois.list();
..
and later in the controller
tournois.findinscris(cid)

use this. $scope.isloading would be false, when comes response
baclyApp.controller('ContentsCtrl', function ($scope, ContentService) {
$scope.isloading = true;
ContentService.getContent("getContent.php", function (contents) {
$scope.contents = contents;
$scope.isloading = false;
}, function () {
$scope.isloading = false;
});
// contents.getContent("another.php", function (data) {
// $scope.contents = data;
// });
console.log($scope.contents);
});
baclyApp.service("ContentService", function ($http, $cookies) {
var urlphp = "http://bacly.fr/baclymphp/";
function getRequest(method, url, data, onSuccess, onError) {
var header = {}
$http({
method: method,
url: urlphp + url,
data: data
}).then(function () {
if (onSuccess) {
onSuccess(contents);
}
}, function () {
if (onError) onError();
});
}
function getContent(url, onSuccess, onError) {
getRequest("GET", url, null, onSuccess, onError);
}
function getOtherContent(url, onSuccess, onError) {
getRequest("POST", url, null, onSuccess, onError);
}
return {
getRequest: getRequest
getContent: getContent,
getOtherContent: getOtherContent
}
});
Also, I recommend that:
services, factories, controllers names should be capital letter. methods isn't.
use "service" to work with API.
use "factory" to transfer data among controllers.
UPDATED:
baclyApp.factory("tournois", function ($http, $q) {
//Factory qui recupère les données de tournois et iscriptions
// var urlphp="http://localhost/cordova/mbacly/www/php/";
var tournois = {},
urlphp = "http://bacly.fr/baclymphp/",
phpFiles = {
getTournois: "getTournois.php",
getTournoinscriptions: "getTournoinscriptions.php",
getTournoinscris: "getTournoinscris.php",
getUsers: "getUsers.php"
},
countResponse = 0;
function getDate(from, onSuccess, onError) {
$http.get(urlphp + from).then(function (response) {
if (response) {
if (onSuccess) {
onSuccess(response)
}
} else if (onError) {
onError()
}
}, function () {
onError();
})
}
getDate(phpFiles.getTournois, function (response) {
tournois.tournois = response.data;
countResponse++;
console.log(tournois);
}, function () {
alert("pas d acces réseau");
});
getDate(phpFiles.getTournoinscriptions, function (response) {
tournois.inscriptions = response.data;
countResponse++;
}, function () {
alert("pas d acces réseau");
});
getDate(phpFiles.getTournoinscris, function (response) {
tournois.inscris = response.data;
countResponse++;
}, function () {
alert("pas d acces réseau");
});
getDate(phpFiles.getUsers, function (response) {
tournois.users = response.data;
countResponse++;
}, function () {
alert("pas d acces réseau");
});
return {
getResponseAfterSuccess: function (onSuccess, onError) {
if (Object.keys(phpFiles).length == countResponse) {
if (onSuccess) onSuccess(tournois);
} else {
if (onError) onError(tournois);
}
},
list: function () {
return tournois;
}
//, more codes
}
});
baclyApp.controller('tournoisCtrl', ['$scope', 'tournois', '$cookies', '$state', '$window', 'growl', function ($scope, tournois, $cookies, $state, $window, growl) {
//Liste des tournois
$scope.showtournoislist = true;
$scope.isloading = true;
$scope.tournois = tournois.getResponseAfterSuccess(function (response) {
$scope.tournois = response;
$scope.isloading = false;
$scope.showtournoislist = false;
}, function (response) {
$scope.tournois = response;
});
}]);

Related

How do I populate html using angular controller prior to display

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=&nbsp&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=&nbsp&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>

How to call service in angularjs

(function() {
'use strict';
angular
.module('autocompleteCustomTemplateDemo', ['ngMaterial'])
.controller('DemoCtrl', DemoCtrl);
function DemoCtrl($timeout, $q, $log, $scope, $http) {
var self = this;
$scope.service_details = [];
$scope.productdetail == [];
$scope.add = function() {
$scope.show_servicelist = true;
$scope.type = function(e) {
alert(e);
}
$scope.service_details.push(JSON.parse($scope.productdetails));
}
self.simulateQuery = false;
self.isDisabled = false;
self.repos = loadAll();
self.querySearch = querySearch;
self.selectedItemChange = selectedItemChange;
self.searchTextChange = searchTextChange;
function querySearch(query) {
var results = query ? self.repos.filter(createFilterFor(query)) : self.repos,
deferred;
if (self.simulateQuery) {
deferred = $q.defer();
$timeout(function() {
deferred.resolve(results);
}, Math.random() * 1000, false);
return deferred.promise;
} else {
return results;
}
}
function searchTextChange(text) {
$log.info('Text changed to ' + text);
}
function selectedItemChange(item) {
$log.info('Item changed to ' + JSON.stringify(item));
$scope.productdetails = JSON.stringify(item);
}
function loadAll() {
var repos = [{
'product_gid': '1',
'product_name': 'stabilizer',
'forks': '16,175',
}, {
'product_gid': '2',
'product_name': 'stand',
'forks': '760',
}, {
'product_gid': '3',
'product_name': 'ac',
'forks': '1,241',
},
];
return repos.map(function(repo) {
repo.value = repo.product_name.toLowerCase();
return repo;
});
}
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(item) {
return (item.value.indexOf(lowercaseQuery) === 0);
};
}
}
})();
app.service("productservice", function($http) {
this.getproduct = function() {
deggure
var response = $http.get("/Productjson/");
return response;
}
});
I'm displaying angularjs file for listing autocomplete, now i have added new service file to get some data.I want to send the service data into app code, i dont know how to connect service with controller code.when i try to connect i got syntax error. please modify the code and guide me to fetch the service data .
This is full sample to show you how to use service in angularjs with controller:
var app = angular.module("app", []);
app.controller("ctrl", function($scope, service) {
$scope.alert = function() {
service.alert();
}
$scope.console = function() {
service.console();
}
})
app.service("service", function() {
this.alert = function() {
alert("hey")
}
this.console = function() {
console.log("hey")
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<button ng-click="alert()">alert</button>
<button ng-click="console()">console</button>
</div>
This is how you write a service-
I prefer factory:
(function() {
'use strict';
angular
.module('app')
.factory('productservice', productservice);
function productservice($q, $http) {
return {
getproduct : getproduct
};
function getproduct(){
var d = $q.defer();
$http({
method: 'GET',
url: 'url'
}).success(function(response){
d.resolve(response);
}).error(function(response){
d.reject(response);
});
return d.promise;
}
}
})();
Here;s controller
(function() {
'use strict';
angular
.module('app')
.controller('AppController', AppController);
function AppController(
$scope, productservice
) {
function getproduct(){
productservice.getproduct().then(function(response){
//got the response here
}, function(){
});
}
}
})();

Using asynchronous data from one factory in another factory

I'm trying to use geolocation data from one factory in angular in another factory that queries a weather API for data. I cannot figure out how to share the lat/lng variables between the two factories, I know you have use $scope but I cannot get the angular-promise to work correctly. Currently there are static lat/lng variables. The locate function in the controller doesn't even print to console, I think there's something wrong with my promise function.
Here are the factories:
'use strict';
app.config(['$resourceProvider', function ($resourceProvider) {
$resourceProvider.defaults.stripTrailingSlashes = false;
}]);
app.factory("geolocationService", ['$q', '$window', '$rootScope', function ($q, $window, $rootScope) {
return {
currentLocation: function() {var deferred = $q.defer();
if (!$window.navigator) {
$rootScope.$apply(function() {
deferred.reject(new Error("Geolocation is not supported"));
});
} else {
$window.navigator.geolocation.getCurrentPosition(function (position) {
$rootScope.$apply(function() {
deferred.resolve(position);
var geoJ = $scope.data;
//console.log(position);
});
}, function (error) {
$rootScope.$apply(function() {
deferred.reject(error);
});
});
}
return deferred.promise;
}
}
}]);
app.factory('weatherFactory', ['$http','geolocationService', function ($http, $scope, geolocationService) {
//var currentLocation = geolocationService.currentLocation();
var apiKey = 'd079ba76e47f06f2ea3483892f1b1d40';
var lat = '40',
lon = '-79';
return {
currentForecast: function(callback){
var url = ['https://api.forecast.io/forecast/', apiKey, '/', lat, ',', lon, '?callback=JSON_CALLBACK'].join('');
$http.jsonp(url)
.success(function (data){
callback(null, data);
//console.log("weatherFactory API Call: ");
//console.log(data);
})
.error(function (error) {
callback(error);
});
}
};
}]);
And here is the controller
app.controller('weatherCtrl', function ($scope, $window, weatherFactory, geolocationService) {
//console.log(geolocationService.currentLocation());
//var location = geolocationService.currentLocation();
//console.log("location object: ");
//console.log(location);
var locate = function(){
geolocationService.currentLocation().then(function(location){
$scope.location = location;
console.log($scope.location);
});
};
var pollForecast = function pollForecast() {
var commutes = calculateNextCommutes();
weatherFactory.currentForecast(function (err, data) {
if (err) {
$scope.forecastError = err;
} else {
$scope.forecast = data;
$scope.nextCommute = findCommuteWeather(commutes.nextCommute, $scope.forecast.hourly.data);
$scope.nextNextCommute = findCommuteWeather(commutes.nextNextCommute, $scope.forecast.hourly.data);
}
});
};
$scope.init = function () {
pollForecast();
setInterval(function () {
console.log('polling weather every hour')
pollForecast();
}, 1000 * 60 * 60); //poll every hour
}
});
I'm very new to Angular and would appreciate any help from the community, I'd like to be more active on here! Thanks in advance.
Best Regards,
-MC
First of all, DONT USE $SCOPE IN FACTORY, $scope is only available on controllers.
The solution for you problem is very simple. Have weatherFactory expose the lat/long by returning them:
return {
lat: lat,
lon: lon,
currentForecast: function(callback){
var url = ['https://api.forecast.io/forecast/', apiKey, '/', lat, ',', lon, '?callback=JSON_CALLBACK'].join('');
$http.jsonp(url)
.success(function (data){
callback(null, data);
//console.log("weatherFactory API Call: ");
//console.log(data);
})
.error(function (error) {
callback(error);
});
}
};
And then, inject weatherFactory into geolocationService and you'll be able to access lat/lon:
app.factory("geolocationService", ['$q', '$window', '$rootScope', 'weatherFactory', function ($q, $window, $rootScope , weatherFactory) {
return {
currentLocation: function() {var deferred = $q.defer();
var lat = weatherFactory.lat;
var lon = weatherFactory.lon;
if (!$window.navigator) {
$rootScope.$apply(function() {
deferred.reject(new Error("Geolocation is not supported"));
});
} else {
$window.navigator.geolocation.getCurrentPosition(function (position) {
$rootScope.$apply(function() {
deferred.resolve(position);
var geoJ = $scope.data;
//console.log(position);
});
}, function (error) {
$rootScope.$apply(function() {
deferred.reject(error);
});
});
}
return deferred.promise;
}
}
}]);
How about this:
app.factory("geolocationService", ['$q', '$window', '$rootScope', function ($q, $window, $rootScope) {
return {
currentLocation: function() {
var deferred = $q.defer();
if (!$window.navigator) {
$rootScope.$apply(function() {
deferred.reject(new Error("Geolocation is not supported"));
});
} else {
$window.navigator.geolocation.getCurrentPosition(function (position) {
$rootScope.$apply(function() {
deferred.resolve(position);
});
}, function (error) {
$rootScope.$apply(function() {
deferred.reject(error);
});
});
}
return deferred.promise;
}
}
}]);
app.service('weatherService', ['$http','geolocationService', function ($http, $scope, geolocationService) {
var apiKey = '...';
return function(callback){
//Note - a better, more angularish way to do this is to return the promise
//itself so you'll have more flexability in the controllers.
//You also don't need callback param because angular's $http.jsonp handles
//that for you
geolocationService.currentLocation().then(function(location){
var url = ['https://api.forecast.io/forecast/', apiKey, '/', location.lat, ',', location.lon, '?callback=JSON_CALLBACK'].join('');
return $http.jsonp(url)
.then(function(data){ callback(null,data); })
catch(callback);
}
};
}]);

Angular controller function minification error

I have the Angular controller below. When it is run, I get the error "TypeError: t.getDealers is not a function". This is caused by the minification of the javascript. However, I'm not sure how to fix this.
myApp.controller('DLOController', ['$scope', 'DLOFactory',
function ($scope, DLOFactory) {
$scope.init = function () {
$scope.searchType = [{ id: 1, name: "Search by Postcode" }, { id: 2, name: "Search by State" }, { id: 3, name: "Search by Dealer" }];
$scope.selectedSearchType = 1;
$scope.selectedState = -1;
$scope.postcode = "";
$scope.dealerName = "";
$scope.states = [];
$scope.dealers = [];
getStates(2);
getDealers(2);
}
function getStates(categoryType) {
DLOFactory.getStates(categoryType)
.success(function (val) {
$scope.states = val;
})
.error(function (error) {
// REVISIT: LOG ERROR HERE.
});
}
function getDealers(categoryType) {
DLOFactory.getDealers(categoryType)
.success(function (val) {
$scope.dealers = val;
console.log($scope.dealers);
})
.error(function (error) {
// REVISIT: LOG ERROR HERE.
});
}
}
]);
Here is my factory:
myApp.factory('DLOFactory', ['$http', function ($http) {
var stateList = [];
var dealerList = [];
return {
getStates: function (categoryType) {
return $http({
method: 'GET',
url: '/Addresses/GetStateList',
params: { categoryType: categoryType }
})
.success(function (responseData) {
stateList.push(responseData);
});
},
getStateList: function () {
return stateList;
},
setStateList: function (sl) {
stateList = sl;
}
}
return {
getDealers: function (categoryType) {
return $http({
method: 'GET',
url: '/Websites/GetDealers',
params: { categoryType: categoryType }
})
.success(function (responseData) {
dealerList.push(responseData);
});
},
getDealerList: function () {
return dealerList;
},
setDealerList: function (dl) {
dealerList = dl;
}
}
}]);
The minified code looks like this:
myApp.controller("DLOController",["$scope","DLOFactory",function(n,t){function i(i){t.getStates(i).success(function(t){n.states=t}).error(function(){})}function r(i){t.getDealers(i).success(function(t){n.dealers=t;console.log(n.dealers)}).error(function(){})}n.init=function(){n.searchType=[{id:1,name:"Search by Postcode"},{id:2,name:"Search by State"},{id:3,name:"Search by Dealer"}];n.selectedSearchType=1;n.selectedState=-1;n.postcode="";n.dealerName="";n.states=[];n.dealers=[];i(2);r(2)}}]);
You have two returns on the factory so second return won't execute. So merge both returns & try.

How to test a controller function calling a private function that in turn calls a asynchronous function in angularjs

[plunkr][1]http://plnkr.co/edit/Jk1Rp3nEgUQTmDOs3xBl?p=preview
My current code is structured as below.
angular.module("app",[])
.service("dataService",function($http){
this.get = function (url) {
return $http.get(url);
};
})
.service("mainService",function(dataService){
this.getData = function(pattern){
return dataService.get(pattern+"/abc");
}
})
.controller("mainController",function($scope,mainService){
$scope.refreshData = function(pattern){
loadData(pattern);
}
function loadData(pattern){
mainService.getData(pattern)
.success(function(data){
console.log(data);
})
.error(function(error){
console.log(error);
})
}
})
I have been trying to make sense of how to test it by reading blogs but each blog has either a different approach or the blog is 2-3 years old. I would like to know how do I test the controller?
Should I test each function? If yes, then how should I test the private function? Is using the private function a good idea or should I just add the private function code to the scoped function?
Also is there any better way to do write this function?
Most important part where we are going to create stub:
beforeEach(function() {
var $httpResponse = {
success: function() {
return $httpResponse;
},
error: function() {
return $httpResponse;
}
};
var _stubMainService_ = {
getData: jasmine.createSpy('getData').and.returnValue($httpResponse)
};
angular.module('app')
.value('mainService', _stubMainService_);
});
and test that uses it:
it('rereshes data', function() {
var pattern = 'abcde';
scope.refreshData(pattern);
expect(mainService.getData).toHaveBeenCalledWith(pattern);
});
angular.module("app", [])
.service("dataService", function($http) {
this.get = function(url) {
return $http.get(url);
};
})
.service("mainService", function(dataService) {
this.getData = function(pattern) {
return dataService.get(pattern + "/abc");
}
})
.controller("mainController", function($scope, mainService) {
$scope.refreshData = function(pattern) {
loadData(pattern);
}
function loadData(pattern) {
mainService.getData(pattern)
.success(function(data) {
console.log(data);
}).error(function(error) {
console.log(error);
})
}
})
describe('mainController()', function() {
var scope, controller, mainService, $q;
beforeEach(module('app'));
beforeEach(function() {
var $httpResponse = {
success: function() {
return $httpResponse;
},
error: function() {
return $httpResponse;
}
};
var _stubMainService_ = {
getData: jasmine.createSpy('getData').and.returnValue($httpResponse)
};
angular.module('app')
.value('mainService', _stubMainService_);
});
beforeEach(inject(function($controller, $rootScope, _mainService_) {
scope = $rootScope.$new();
controller = $controller('mainController', {
$scope: scope
});
mainService = _mainService_;
}));
it('rereshes data', function() {
var pattern = 'abcde';
scope.refreshData(pattern);
expect(mainService.getData).toHaveBeenCalledWith(pattern);
});
})
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-mocks.js"></script>

Categories

Resources