Angular app only shows adjusted dynamic content after refresh - javascript

I'm using a service(factory) to access my data on the server side, I'm using $routeParams to include the id to the request to the server. And this all works perfectly fine, but only the first time I run through the program, here is some of my code:
my controller:
klusplan.success(function(data) {
console.log("onsucces",data);
$scope.klusplan = data[0];
$scope.klusplan.duratie = localStorage.getItem('Duration');
$scope.klusplan.orderId = localStorage.getItem('klusplan');
var tijdInUren = localStorage.getItem('Duration').split(":");
var Uren = tijdInUren[0];
var Minuten = tijdInUren[1];
Uren = Uren + (Minuten / 60);
$scope.klusplan.kosten = ($scope.klusplan.vm_kl_tarief * Uren);
});
my service:
app.factory('klusplan', ['$http', '$routeParams', function($http, $routeParams) {
return $http.get('http://localhost:8080/getdata/klusplan.php?id='+$routeParams.klplan_id)
.success(function(data, status) {
console.log("succes", data, status);
return data;
})
.error(function(err) {
return err;
});
}]);
and last but not least the route
.when('/klusplan/:klplan_id', {
controller: 'KlusplanController',
templateUrl: 'views/klusplan.html'
})
I've already tried some things like:
$httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
$httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
$httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
and
app.run(function($rootScope, $templateCache) {
$rootScope.$on('$routeChangeStart', function(event, next, current) {
console.log("event: ", event," next: ", next," current: ", current)
$templateCache.remove(current.templateUrl);
});
});
Now the voodoo all starts when I run through my application for the second time, instead of getting the data from the server, the http request never fires. Instead it shows me the data gathered from the last time I ran through it.
I would appreciate any and all help.

You are calling the klusplan.success function directly. So you will always get the already fetched data.
If you write the factory like this:
app.factory('klusplan', ['$http', '$routeParams', function($http, $routeParams) {
return {
getData: function() {
return $http.get('http://localhost:8080/getdata/klusplan.php?id='+$routeParams.klplan_id);
}
};
}]);
And then inside the controller:
klusplan.getData().then(function(data) { ...
So you call everytime $http.get and getting new Data from the server instead of just the already successful fetched data.

Related

Set Angularjs Service data to Controller Variable

I am trying to set the controllers scope variable to the data, however no luck. The console.log in the controller shows undefined. Appreciate the help!
My angular service has the following code --
service('VyrtEventService', ['$http', function($http) {
var events = [];
this.getArtistEvents = function(artistId) {
var url = '/api/users/' + artistId + '/';
var promise = $http.get(url).success(function(data, status, headers, config) {
events = data.artist.events;
console.log(events);
return events;
}).catch(function(error) {
status = 'Unable to load artist data: ' + error.message;
console.log(status);
});
return promise;
};
}]);
And I am referencing it in the controller as follows --
VyrtEventService.getArtistEvents($scope.artistId).then(function(data){
$scope.events = data.data.artist.events;
});
console.log($scope.events);
You should just set $scope.events = data in your controller cause your promise already returns data.artist.events when it resolves
To pass scope to service from anywhere in controller. Make sure you inject service .
controllersModule.controller('MyCtrl', function($scope, $filter, $http, $compile, ngTableParams, **FactoryYouwant**)
{
**FactoryYouwant**.getdata($scope.**scopeYoutwantTopass**).then (function(responseData){
var ResponseFromServer =responseData.data;
}
in service
controllersModule.factory('**FactoryYouwant**, function($http) {
var responseData = null;
return {
getdata : function(**data**){ (you dont have to use $)
responseData = $http.post or whatever actually gets you data;
return responseData;
}
};
});
I hope this helps you to call get data from service anywhere in controller.

Angularjs Service Injection Issue

I'm trying to add a service to my Angular project for the first time and running into issues injecting it within my controller.
I am getting an error of --
TypeError: Cannot read property 'get' of undefined
I'm looking to properly inject the service into the controller and ways I can improve the code for best practices/efficiency.
Thanks for the help!
I have a folder /event in my angular project with the following files --
app.js
controllers.js
directives.js
services.js
app.js file has --
'use strict';
angular.module('vyrt.event', [
'vyrt.event.controllers',
'vyrt.event.services',
'vyrt.event.directives'
]);
services.js file has --
'use strict';
angular.module('vyrt.event.services', []).
service('VyrtEventService', ['$http', function($http) {
var artistId = 0,
artist = '',
events = [],
active_event_idx = 0;
this.get = function(artistId) {
var url = '/api/users/' + artistId + '/';
$http.get(url).success(function(data, status, headers, config) {
artist = data.artist.user;
events = data.artist.events;
active_event_id = data.artist.events[0].id;
});
return artist, events, active_event_id;
}
}]);
finally, the controller has --
'use strict';
angular.module('vyrt.event.controllers', []).
controller('VyrtEventCtrl', ['$scope', function($scope, VyrtEventService) {
console.log(VyrtEventService.get($scope.artistId));
$scope.activeCampaign = function(idx) {
if (idx == VyrtEventService.active_event_idx) return true;
return false;
};
}]);
The problem is that you've forgotten to put 'VyrtEventService' in your dependency list when you define you controller:
.controller('VyrtEventCtrl', ['$scope', /* you need this ==>*/ 'VyrtEventService', function($scope, VyrtEventService) {
console.log('VyrtEventService', VyrtEventService);
$scope.activeCampaign = function(idx) {
if (idx == VyrtEventService.active_event_idx) return true;
return false;
};
}]);
Update
Your get() function has a couple of issues. First, you need to return the $http.get() call itself and then you can call then() in your controller and set the results to a property on your $scope there. Second, you can't return multiple values like that. You would have to return an array of values or an object with your desired values assigned to it.
service
this.get = function(artistId) {
var url = '/api/users/' + artistId + '/';
return $http
.get(url)
.catch(function(error){
// handle errors here
console.log('Error fething artist data: ', error);
});
}
controller
VyrtEventService
.get(artistId)
.then(function(data){
$scope.artist = data.artist.user;
$scope.events = data.artist.events;
$scope.active_event_id = data.artist.events[0].id;
});
$scope.activeCampaign = function(idx) {
return (idx == $scope.active_event_idx);
};

Getting the object obtained from asynchronous $http service in angularJS to be accessible globally in $scope

I am working using Angular JS. I am trying to get a json object obtained using $http service to be accessible in a $scope variable. Inside all the asynchronous AJAX ($http.get()) calls, if I try to print the data obtained stored inside a $scope variable and print it, it works successfully and shows me the expected data. But outside scope of the asynchronous method, the same $scope variable assigned with data obtained loses hold of it and prints undefined.
Code:
var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q) {
return {
list: function(){
var deferred = $q.defer();
$http.get('/testcase/' + $routeParams.testcase)
.success(function(data, status, headers, config) {
deferred.resolve(data);
})
.error(function(data, status, headers, config) {
deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
});
return deferred.promise;
}
};
}
]);
app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$http', 'getTestcaseFactory', function($scope, $routeParams, $http, getTestcaseFactory) {
$scope.myjsonobj = '';
var fetchTestcaseDetails = function() {
getTestcaseFactory.list()
.then(
function(data) {
$scope.xml.file = data;
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json($scope.xml.file);
$scope.xml.json = JSON.stringify(jsonObj, null, 2);
$scope.model = jsonObj;
console.log($scope.model);//PRINTS THE RIGHT DATA
},
function(data) {
alert(data);
});
}
fetchTestcaseDetails();
console.log($scope.model); //Prints undefined
}]);
By the time
console.log($scope.model);
executes, the $http request would have not gone through yet, and this is why it prints undefined. Once the $http request is done, your $scope.model will update accordingly. You can test this by using a $timeout
$timeout(function () {
console.log($scope.model);
}, 5000);
Don't forget to inject $timeout in your controller.
This saves my day! $timeout to the rescue. Thanks #Dan Moldovan for the answer! As the $http service is asynchronous, we have to set a timer to wait for a time interval till the point the data is really received in the promise.success section and then it can be assigned to a variable inside $scope.
var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q) {
return {
list: function(){
var deferred = $q.defer();
$http.get('/testcase/' + $routeParams.testcase)
.success(function(data, status, headers, config) {
deferred.resolve(data);
})
.error(function(data, status, headers, config) {
deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
});
return deferred.promise;
}
};
}
]);
app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$timeout', 'getTestcaseFactory', function($scope, $routeParams, $timeout, getTestcaseFactory) {
var fetchTestcaseDetails = function() {
getTestcaseFactory.list()
.then(
function(data) {
$scope.xml.file = data;
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json($scope.xml.file);
$scope.xml.json = JSON.stringify(jsonObj, null, 2);
$scope.model = jsonObj;
console.log($scope.model);//PRINTS THE RIGHT DATA
},
function(data) {
alert(data);
});
}
fetchTestcaseDetails();
$timeout(function() {
console.log($scope.model); //Prints the Data now
}, 2000);
}]);
The solutions posted so far are fundemantally wrong, as they depend on an arbitrary timeout, and nothing guarantees that the async answer will be available by then.
As I suggested in a comment above, here are 2 more data/event-driven solutions.
You either only print in the callback function (which you're already doing in your example)
Or since you're using angular anyway, you can set up a watch (which in the background uses a not-too-nice dirty checking solution, but at least it's abstracted away from your code)
If you want to run a function called processData once the data is available, solution 1 you already do in your example, see this line:
console.log($scope.model);//PRINTS THE RIGHT DATA
Here you could call any other function to trigger the continuation of the process, just call whatever function:
console.log($scope.model);//PRINTS THE RIGHT DATA
processData();
Using angular's $watch mechanism (2.):
$scope.$watch(
function(){return $scope.model;},
function(newValue, oldValue){
if(newValue != null){
console.log($scope.model);
processData();
}
})
This will print the data when it is available after the async callback, and the program will continue with processing from then.

AngularJS - factory not being called when URL changes

I'm new to Angular JS and struggling to get a factory to return data when my URL has changed.
In my app config I have:
.state('app.sessionActivity', {
url: "/session/:sessionid/activity/:id",
views: {
'menuContent' :{
templateUrl: "templates/activity.html",
controller: 'SessionActivityCtrl'
}
}
})
My Controller:
.controller('SessionActivityCtrl', ['$scope', '$stateParams', 'localJSONData', function($scope, $stateParams, localJSONData) {
var activityID = $stateParams.id;
var activityVideoURLSRC = null;
localJSONData.getJSONData()
.success(function(data){
$scope.activityData = data[activityID - 1];
});
}])
My factory:
.factory('localJSONData', ['$http', '$stateParams', function($http, $stateParams){
var sessionID = $stateParams.sessionid;
return {
getJSONData: function(){
if(sessionID == 1){
return $http.get('json/session1_activities.json', {cache:false});
}
if(sessionID == 2){
return $http.get('json/session2_activities.json', {cache:false});
}
}
}
}])
This all works when I first load the page and go to the URL (for example) /session/1/activity/1 for the first time. But then when I load the URL (for example) /session/2/activity/2 the data is from session 1. When I debug in chrome, the factory doesn't get called the second time.
Am I not getting something conceptually, not using the correct methods, or are there any errors in my code?
The way you're passing in sessionID isn't really a good idea, why don't you pass it to the method in your factory itself?
return {
getJSONData: function(sessionID){
if(sessionID == 1){
return $http.get('json/session1_activities.json', {cache:false});
}
if(sessionID == 2){
return $http.get('json/session2_activities.json', {cache:false});
}
}
Controller:
localJSONData.getJSONData($stateParams.id)
.success(function(data){
$scope.activityData = data[activityID - 1];
});
The reason this works the first time your app loads is because $stateParams correctly evaluates the initial state's parameter, but doesn't update after that. The best way to do it would be what I posted above.

AngularJS 1.2 cross origin requests are only supported for HTTP

Is there any way to configure Angular app to make it available?
Im using a factory.
By the way, I'm using localhost as webserver but I'm making a request to other server (same network).
angular.module('demoApp.factories', [])
.factory('dataFactory', ['$http', function($http) {
var urlBase = 'external-server:8080';
var dataFactory = {};
dataFactory.getTest = function () {
return $http.get(urlBase + '/test');
};
return dataFactory;
}]);
Finally found the solution. Will post here, maybe it can help others:
angular.module('demoApp.factories', [])
.factory('dataFactory', ['$http', function($http) {
var urlBase = 'external-server:8080';
var dataFactory = {};
dataFactory.getTest = function () {
//Note the $http method changed and a new parameter is added (callback)
//the value of the callback parameter can be anything
return $http.jsonp(urlBase + '/test?callback=myCallback');
};
return dataFactory;
}]);
The controller file basically just calling this factory:
angular.module('demoApp.controllers', []).controller('controller1', ['$scope', 'dataFactory',
function ($scope, dataFactory) {
$scope.status;
$scope.data;
dataFactory.getTest().success(function (data)
{
$scope.data = data;
}).error(function (error)
{
$scope.status = 'Unable to load customer data: ' + error.message;
});
You may be looking to configure the $httpProvider as specified here: http://better-inter.net/enabling-cors-in-angular-js/
Another way is to create a simple http proxy on your front-end server to make external requests look like to angular that they're coming from the same server.

Categories