AngularJS update function is (still)not working - javascript

I have a function which updates the object, the problem is when I go back from the update form field to the detailed view, it initializes the old object instead of the updated object.
I want to populate the cars list in the CarService instead of the app.js
This is my carService:
window.app.service('CarService', ['HTTPService', '$q',
'$http', function (HTTPService, $q, $http) {
'use strict';
this.cars = [];
this.get = function () {
var deferred = $q.defer();
HTTPService.get('/car').then(function resolve(response) {
deferred.resolve(response.data);
}, function reject(response){
deferred.reject(response);
});
};
this.add = function (formCar) {
var deferred = $q.defer();
console.log("CarService response 1 : ");
$http.post('/#/car', formCar).then(function resolve(response){
deferred.resolve(response.data);
}, function reject(response){
deferred.reject(response);
});
return deferred.promise;
};
this.showDetails = function (carId){
var deferred = $q.defer();
$http.get('/car/view/{{carId}}').then(function resolve(response){
HTTPService.get('/car/view/' + carId).then(function
resolve(response) {
deferred.resolve(response.data);
}, function reject(response){
deferred.reject(response);
});
return deferred.promise;
};
this.put = function (carformUpdate, opleidingsprofielId) {
var deferred = $q.defer();
$http.put('/#/car/:carId/update', carformUpdate).then(function resolve(response){
deferred.resolve(response.data);
}, function reject(response){
deferred.reject(response);
});
return deferred.promise;
};
}]);
This is my updateCar controller:
window.app.controller('updateCarCtrl', ['$scope', '$routeParams',
'CarService', '$location', function ($scope, $routeParams, CarService,
$location) {
'use strict';
$scope.carId = $routeParams.carId;
initCar($scope.carId);
function initCar(carId) {
CarService.showDetails(carId).then(function success(car) {
$scope.car = car;
}, function error(response) {
});
}
$scope.updateCar = function (carId) {
carId = $scope.carId;
if($scope.car !== null){
CarService.put($scope.car, carId).then(function
success(response) {
$scope.car = response;
$location.path('/car/view/' + carId);
alert("Car updated");
}, function error(response) {
$scope.error = response.statusText;
$scope.myform = {};
});
}
};
}]);
This is my carView controller:
window.app.controller('carViewCtrl', ['$scope', '$routeParams', '$location',
'CarService', function ($scope, $routeParams, $location, CarService) {
'use strict';
$scope.carId = $routeParams.carId;
initCar($scope.carId);
function initCar(carId) {
CarService.showDetails(carId).then(function success(car) {
$scope.car = car;
}, function error(response) {
});
}
}]);
My carView initializes the object again when it gets redirected with $location.path('/car/view/' + carId); but as the original object and not the updated object.
I'm trying to do this on an ngMock backend.
My app.js looks like this:
App.js
routing:
.when('/car', {
templateUrl: 'pages/car/car.html'
})
.when('/car/view/:carId', {
templateUrl: 'pages/car/carView.html',
controller: 'carViewCtrl',
controllerAs: 'ctrl'
})
.when('/car/addCar', {
templateUrl: 'pages/car/carAdd.html'
})
.when('/car/:carId/update', {
templateUrl: 'pages/car/carUpdate.html',
controller: 'updateCarCtrl',
conrtollerAs: 'ctrl'
})
app.run: this is where my mock backend is defined
window.app.run(function($httpBackend) {
var cars = [
{
id: 0,
name: ‘car0’,
address: 'adress0',
tel: 'tel0',
email: 'email0'},
{
id: 1,
name: ‘car1’,
address: 'adress1',
tel: 'tel1',
email: 'email1'
}];
var carUrl = “/#/car”;
$httpBackend.whenGET(carUrl).respond(function(method,url,data) {
return [200, cars, {}];
});
$httpBackend.whenGET(/\/#\/car\/view\/(\d+)/, undefined,
['carId']).respond(function(method, url, data, headers, params) {
return [200, cars[Number(params.carId)], {
carId : params.carId
}];
});
$httpBackend.whenPUT('/#/car/:carId/update').respond(function(method, url,
data, carId) {
var car = angular.fromJson(data);
return [200, car, {}];
});
Thanks for any help!

It looks like your update function calls the CarService.put, which in turn calls a HTTPService.put. In your mocked backend you have this:
$httpBackend.whenPUT
-> add new car;
So it always adds a new car, and doesn't update one. This means that when you do the get, you probably get the first car back that matches the given id, which isn't the updated one.
In pseudo code:
// carService.cars = [{id:1,name:"name"}]
var myCar = carService.get(1); // returns {id:1,name:"name"}
myCar.name = "otherName";
carService.put(car); // -> cars.push(car); -> cars = [{id:1,name:"name"},{id:1,name:"otherName"}]
goToDetails(1);
var myCar = carService.get(1); // iterate over the cars, and return the one with id = 1,
// which is {id:1,name:"name"}

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>

Update function AngularJs is not working [duplicate]

I have a function which updates the object, the problem is when I go back from the update form field to the detailed view, it initializes the old object instead of the updated object.
I want to populate the cars list in the CarService instead of the app.js
This is my carService:
window.app.service('CarService', ['HTTPService', '$q',
'$http', function (HTTPService, $q, $http) {
'use strict';
this.cars = [];
this.get = function () {
var deferred = $q.defer();
HTTPService.get('/car').then(function resolve(response) {
deferred.resolve(response.data);
}, function reject(response){
deferred.reject(response);
});
};
this.add = function (formCar) {
var deferred = $q.defer();
console.log("CarService response 1 : ");
$http.post('/#/car', formCar).then(function resolve(response){
deferred.resolve(response.data);
}, function reject(response){
deferred.reject(response);
});
return deferred.promise;
};
this.showDetails = function (carId){
var deferred = $q.defer();
$http.get('/car/view/{{carId}}').then(function resolve(response){
HTTPService.get('/car/view/' + carId).then(function
resolve(response) {
deferred.resolve(response.data);
}, function reject(response){
deferred.reject(response);
});
return deferred.promise;
};
this.put = function (carformUpdate, opleidingsprofielId) {
var deferred = $q.defer();
$http.put('/#/car/:carId/update', carformUpdate).then(function resolve(response){
deferred.resolve(response.data);
}, function reject(response){
deferred.reject(response);
});
return deferred.promise;
};
}]);
This is my updateCar controller:
window.app.controller('updateCarCtrl', ['$scope', '$routeParams',
'CarService', '$location', function ($scope, $routeParams, CarService,
$location) {
'use strict';
$scope.carId = $routeParams.carId;
initCar($scope.carId);
function initCar(carId) {
CarService.showDetails(carId).then(function success(car) {
$scope.car = car;
}, function error(response) {
});
}
$scope.updateCar = function (carId) {
carId = $scope.carId;
if($scope.car !== null){
CarService.put($scope.car, carId).then(function
success(response) {
$scope.car = response;
$location.path('/car/view/' + carId);
alert("Car updated");
}, function error(response) {
$scope.error = response.statusText;
$scope.myform = {};
});
}
};
}]);
This is my carView controller:
window.app.controller('carViewCtrl', ['$scope', '$routeParams', '$location',
'CarService', function ($scope, $routeParams, $location, CarService) {
'use strict';
$scope.carId = $routeParams.carId;
initCar($scope.carId);
function initCar(carId) {
CarService.showDetails(carId).then(function success(car) {
$scope.car = car;
}, function error(response) {
});
}
}]);
My carView initializes the object again when it gets redirected with $location.path('/car/view/' + carId); but as the original object and not the updated object.
I'm trying to do this on an ngMock backend.
My app.js looks like this:
App.js
routing:
.when('/car', {
templateUrl: 'pages/car/car.html'
})
.when('/car/view/:carId', {
templateUrl: 'pages/car/carView.html',
controller: 'carViewCtrl',
controllerAs: 'ctrl'
})
.when('/car/addCar', {
templateUrl: 'pages/car/carAdd.html'
})
.when('/car/:carId/update', {
templateUrl: 'pages/car/carUpdate.html',
controller: 'updateCarCtrl',
conrtollerAs: 'ctrl'
})
app.run: this is where my mock backend is defined
window.app.run(function($httpBackend) {
var cars = [
{
id: 0,
name: ‘car0’,
address: 'adress0',
tel: 'tel0',
email: 'email0'},
{
id: 1,
name: ‘car1’,
address: 'adress1',
tel: 'tel1',
email: 'email1'
}];
var carUrl = “/#/car”;
$httpBackend.whenGET(carUrl).respond(function(method,url,data) {
return [200, cars, {}];
});
$httpBackend.whenGET(/\/#\/car\/view\/(\d+)/, undefined,
['carId']).respond(function(method, url, data, headers, params) {
return [200, cars[Number(params.carId)], {
carId : params.carId
}];
});
$httpBackend.whenPUT('/#/car/:carId/update').respond(function(method, url,
data, carId) {
var car = angular.fromJson(data);
return [200, car, {}];
});
Thanks for any help!
It looks like your update function calls the CarService.put, which in turn calls a HTTPService.put. In your mocked backend you have this:
$httpBackend.whenPUT
-> add new car;
So it always adds a new car, and doesn't update one. This means that when you do the get, you probably get the first car back that matches the given id, which isn't the updated one.
In pseudo code:
// carService.cars = [{id:1,name:"name"}]
var myCar = carService.get(1); // returns {id:1,name:"name"}
myCar.name = "otherName";
carService.put(car); // -> cars.push(car); -> cars = [{id:1,name:"name"},{id:1,name:"otherName"}]
goToDetails(1);
var myCar = carService.get(1); // iterate over the cars, and return the one with id = 1,
// which is {id:1,name:"name"}

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);
}
};
}]);

Send data through a POST request from Angular factory

I have this in the controller
angular.module('myApp')
.controller('TaskController', function ($scope, TaskFactory) {
$scope.addTodo = function () {
$scope.todos.push({text : $scope.formTodoText});
$scope.formTodoText = '';
};
});
and this in the factory
angular.module('myApp')
.factory('TaskFactory', function ($q, $http) {
var sendTasks = function(params) {
var defer = $q.defer();
console.log(1, params);
$http.post('http://localhost:3000/task/save', params)
.success(function(data) {
console.log(2);
console.log('data', data);
})
.error(function(err) {
defer.reject(err);
});
return defer.promise;
}
return {
sendTask: function(taskData) {
console.log('taskData', taskData);
return sendTasks('/task/save', {
taskData : taskData
})
}
}
});
all I need is to know, how to send the data from the controller to the factory in order to do the POST to the specified route ?
You just need to call the function/method inside factory with the required params.
angular.module('myApp')
.controller('TaskController', function ($scope, TaskFactory) {
$scope.addTodo = function () {
$scope.todos.push({text : $scope.formTodoText});
TaskFactory.sendTask({data : $scope.formTodoText})
$scope.formTodoText = '';
};
});
You can follow Dan Wahlin blog post.
Controller:
angular.module('customersApp')
.controller('customersController', ['$scope', 'dataFactory', function ($scope, dataFactory) {
$scope.status;
dataFactory.updateCustomer(cust)
.success(function () {
$scope.status = 'Updated Customer! Refreshing customer list.';
})
.error(function (error) {
$scope.status = 'Unable to update customer: ' + error.message;
});
}
Factory:
angular.module('customersApp')
.factory('dataFactory', ['$http', function($http) {
var urlBase = '/api/customers';
dataFactory.updateCustomer = function (cust) {
return $http.put(urlBase + '/' + cust.ID, cust)
};
}
Hope that solve your problem.
You can call the function directly on the TaskFactory that you pass into the controller as a dependency.
I've cleaned up your code a bit and created a plunk for you here:
And here's the code:
Controller
(function(angular) {
// Initialise our app
angular.module('myApp', [])
.controller('TaskController', function($scope, TaskFactory) {
// Initialise our variables
$scope.todos = [];
$scope.formTodoText = '';
$scope.addTodo = function() {
// Add an object to our array with a 'text' property
$scope.todos.push({
text: $scope.formTodoText
});
// Clear the input
$scope.formTodoText = '';
// Call function to send all tasks to our endpoint
$scope.sendTodos = function(){
TaskFactory.sendTasks($scope.todos);
}
};
});
})(angular);
Factory
(function(angular) {
angular.module('myApp')
.factory('TaskFactory', function($q, $http) {
var sendTasks = function(params) {
var defer = $q.defer();
$http.post('http://localhost:3000/task/save', params)
.success(function(data) {
console.log('data: ' + data);
})
.error(function(err) {
defer.reject(err);
});
return defer.promise;
}
return {
sendTasks: sendTasks
}
});
})(angular);

AngularJS filter table: $http.get

I am using AngularJS to set up a table and filter its data by a search or category keywords. I
AngularJS
categorieFilter = angular.module("categorieFilter", [])
categorieFilter.controller("catFilter", ["$scope", "store", function($scope, store){
$scope.search = "";
$scope.products = [];
$scope.categories = [];
$scope.categories = store.getCategories();
$scope.products = store.getProducts();
$scope.filterProductsByCats = function(category){
$scope.search = category;
};
}])
categorieFilter.factory('store', function($http){
return {
getCategories: $http.get('api/categories').success(function (data) {
return data;
}),
getProducts : $http.get('api/products').success(function (data) {
return data;
}
};
});
The $http.get on its own is working, when I surf directly to my api I get the required data. Also when I do a alert(data) ifter the $hhtp.get in categories, I get the data I need... So this should be working but it doesn't. I get an error:
TypeError: store.getCategories is not a function
And I got no clue where this is coming from. Anybody a solution to this problem?
When using a factory you should do new function to return a constructor:
function myFactoryFunction() {
return function() {
var a = 2;
this.a2 = function() {
return a*2;
};
};
}
---------------------------------------------------------------------------------
// Injected in your controller
var myShinyNewObject = new myInjectedFactory();
$scope.four = myShinyNewObject.a2();
From this detailed post angular.service vs angular.factory
In your case
var storeFactory = new store();
storeFactory.getProducts();
Updated version, with TS code:
categorieFilter = angular.module("categorieFilter", [])
/**
Store factory
*/
categorieFilter.controller("catFilter", ["$scope", "store", function($scope, store){
$scope.search = "";
$scope.products = [];
$scope.categories = [];
store.getCategories().then(function(data){
$scope.categories = data;
})
store.getProducts().then(function(data){
$scope.products = data;
})
$scope.filterProductsByCats = function(category){
$scope.search = category;
};
}])
/**
Store factory
*/
categorieFilter.factory('store', function($http, $q){
function _getCategory (){
var deferred = $q.defer();
$http.get('api/categories').success(function (data) {
deferred.resolve(data);
})
return deferred.promise;
}
function _getProducts (){
var deferred = $q.defer();
$http.get('api/products').success(function (data) {
deferred.resolve(data);
}
return deferred.promise;
}
return {
getCategories: _getCategory,
getProducts : _getProducts
};
});
I usually create services using $resource. You could try this:
categorieFilter = angular.module("categorieFilter", []);
categorieFilter.factory('categoryStore', [
'$resource',
function($resource) {
return $resource('/api/categories/', {}, {
getCategories: { method: 'GET', params: {} },
});
}
]);
categorieFilter.factory('productsStore', [
'$resource',
function ($resource) {
return $resource('/api/products/', {}, {
getProducts: { method: 'GET', params: {} },
});
}
]);
categorieFilter.controller("catFilter", [
"$scope", "categoryStore", "productsStore", function ($scope, categoryStore, productsStore) {
$scope.search = "";
$scope.products = [];
$scope.categories = [];
$scope.categories = categoryStore.getCategories();
$scope.products = productsStore.getProducts();
$scope.filterProductsByCats = function(category) {
$scope.search = category;
};
}
]);
I usually write http factories passing a callback function parameter (I usually work with Node and I'm used to do this for long working functions). Taking your code it will looks something like this:
categorieFilter = angular.module("categorieFilter", [])
categorieFilter.controller("catFilter", ["$scope", "store", function($scope, store){
$scope.search = "";
$scope.products = [];
$scope.categories = [];
store.getCategories(function(err, data){
if(!err)
$scope.categories = data;
});
store.getProducts(function(err, data){
if(!err)
$scope.products = data;
});
$scope.filterProductsByCats = function(category){
$scope.search = category;
};
}])
categorieFilter.factory('store', function($http){
return {
getCategories: function(next){
$http.get('api/categories')
.success(function (data) {
next(null, data);
})
.error(function(headers, status){
next(status, null);
});
},
getProducts : function(next){
$http.get('api/products')
.success(function (data) {
next(null, data);
})
.error(function(headers, status){
next(status, null);
});
}
};
});
As you can see now factory takes a callback that will be called with error and data parameters, so error handling can be delegate or not to the controller. This is pretty useful for complex situations.
Here's a plunker that works using $q and defer explicitly with some random JSON.
var app = angular.module('categorieFilter', []);
app.factory('store', function($http, $q){
return {
getCategories: function() {
var deferred = $q.defer();
$http.get('https://api.myjson.com/bins/2gamd')
.success(deferred.resolve)
.error(deferred.resolve);
return deferred.promise;
}
}
})
.controller('catFilter', function($scope, store){
store.getCategories().then(function(data) {
$scope.categories = data.stories;// change data.stories to whatever your data is
});
});

Categories

Resources