AngularJS ng-init does not work - javascript

When i go to list.html right after loading the page it doesnt show me the list. I need to go to form.html first and then back to list.html and then it gives me the list. When i had $http functions in controller it worked as i wanted but now that they are in service they dont work like before.
app.js
app.service("dataservice", function($http){
var list = [{}];
this.get = function(){
$http.get("harjoitus22/backend.php").success(function(response){
list = response;
});
};
this.save = function(newcontact){
$http({
method: 'post',
url: 'harjoitus22/backend.php',
data: newcontact,
header: 'Access-Control-Allow-Origin: *'
}).success(function(response){
list = response;
});
};
this.give = function(){
return list;
};
});
app.controller("mainController", function($scope, $location, dataservice){
$scope.save = function(){
dataservice.save($scope.newcontact);
$scope.newcontact = {};
$location.path("/list");
$scope.list = dataservice.give();
};
$scope.get = function(){
dataservice.get();
$scope.list = dataservice.give();
};
});
list.html
<tbody ng-init="get()">
<tr ng-repeat="object in list">
<td>{{object.nimi}}</td>
<td>{{object.email}}</td>
<td>{{object.ruoka}}</td>
<td>{{object.sauna}}</td>
</tr>
</tbody>

$http call works asynchronously, when you call it, It will not give you response on next line execution. To keep eye on that ajax you should take use of promise return by $http method.
For achieving the same you need to return promise object from the service get method ($http methods does return's promise object, which helps you to execute your code by putting up in its .then function's).
Service
this.get = function(){
return $http.get("harjoitus22/backend.php").then(function(res){
list = res.data;
});
};
Controller
dataservice.get().then(function(){
$scope.list = dataservice.give();
});

Related

Returning response data from a 'for loop' - AngularJS

Reasonably new to Angular. I have a service which purpose is to get information from a JSON file, iterate through each object, so I can access the data from the controller. I can access the JSON data from the $http request, but not the JSON data from the for loop within the service.
Is this is the best way to loop through items in AngularJS, if so, how do I access and display this information from the controller?
app.factory('fxRate', ['$http', '$q', function($http, $q){
var factory = {};
factory.getFx = function() {
var deferred = $q.defer();
$http.get('../json/mcfx.json')
.then(
function(response){
var d, i;
var rateData = response.data.fxrate;
for (var i in rateData) {
var fx = rateData[i].usdToEur;
var fxDate = rateData[i].date;
}
deferred.resolve(response.data);
},
function(errResponse){
deferred.reject(errResponse.data);
}
)
return deferred.promise;
}
return factory;
}]);
app.controller('dashboard', ['$scope', 'fxRate', function($scope, fxRate){
$scope.dailyFx = function() {
fxRate.getFx().then(function(data){
console.log(data)
});
}
$scope.dailyFx();
}])
Make it simple., return promise from factory\service and resolve in controller.
Like below:
Factory
app.factory('fxRate', ['$http', function($http){
var factory = {};
factory.getFx = function() {
return $http.get('../json/mcfx.json');
}
return factory;
}]);
Controller
app.controller('dashboard', ['$scope', 'fxRate', function($scope, fxRate){
$scope.dailyFx = function() {
fxRate.getFx().then(function(resonse) {
console.log(resonse.data)
//handle resonse\data, or assign to some $scope property.
var rateData = response.data.fxrate;
for (var i in rateData) {
var fx = rateData[i].usdToEur;
var fxDate = rateData[i].date;
}
});
}
$scope.dailyFx();
}])
To show this data on view\html, you need to assign this to some $scope property, like $scope.fxRateData = response.data.fxrate, and then in html render it the way you want.
For example only :
<div ng-repeat="fxrate in fxRateData track by $index">
<span>{{fxrate.usdToEur}}</span>
<span>{{fxrate.date}}</span>
</div>

AngularJS: Unable to Send $Http JSON Response to View

Trying to get JSON data from an API and show the result in a view using AngularJS. I'm able to get the data correctly but unable to show it in the view.
When i try to access the object's data the result is always undefined.
Here's what i'm doing...
API Service:
myApp.service('apiService', ['$http', function($http)
{
var api = "http://domain.xpto/api/";
var self = this;
this.result;
var apiService =
{
getSection: function(id)
{
var url = api + "section/" + id;
return $http.get(url);
}
}
return apiService;
}]);
Controller:
myApp.controller('mainController', ['$scope', '$routeParams', 'apiService', function($scope, $routeParams, apiService)
{
apiService.getSection(1).then(function(response)
{
$scope.$applyAsync(function ()
{
var data = response.data; //json data as expected
var section = data.section; //undefined?!
var images = data.images; //undefined!?
$scope.title = section.title; //undefined!?
});
});
}]);
JSON Result:
UPDATE: Simplified my apiService based on #Salih's and #elclanrs's suggestion.
Why am i unable to access the inner objects of the json (f.e, data.section.title)?
UPDATE #2: I'm finally able to access the data. It seems i needed an extra data level to get access to the section object of my json array (response.data.data.section). Honesty i don't understand why. I've accessed the API using jquery and it was strait forward...
Edit: I made this plunker to help you!
http://embed.plnkr.co/Yiz9TvVR4Wcf3dLKz0H9/
If I were you, I would use the service function to update the own service value. You already created this.result, you can just update its value.
Your Service:
myApp.service('apiService', ['$http', function($http)
{
var api = "http://domain.xpto/api/";
var self = this;
this.result = {};
this.getSection = function(id){
var url = api + "section/" + id;
$http.get(url).then(function(res){
self.result = res;
});
}
}]);
I wouldn't use a Promise for this case. You can access the Service's var into your Controller and View.
Your controller:
myApp.controller('mainController', ['$scope', '$routeParams', 'apiService',
function($scope, $routeParams, apiService)
{
$scope.apiSer = apiService;
$scope.apiSer.getSection(1);
}]);
In your View:
<pre>{{ apiSer.result }}</pre>
And now you'll see your parameter get updated in real time.
In your getSection function just write and return the following
return $http.get(url);
You might need to use angular.forEach method to parse your inner values of the JSON . Take a look at this example Accesing nested JSON with AngularJS

Change $http parameter in nested ng-repeat

I have two json files being requested for two differents angularjs services.
/people.json
{user-name, user-id}
/task.json
{name-task, task-id, responsible-id}
Where responsible-id = user-id.
I can pass an ID parameter to the task json to request all the task for the user with that ID: /task.json?ID=12
I'm trying to create a nested ng-repeat, the first one to get all the users in /people.json, the second to get all the task for each user in the loop but i ended up with something like this: http://i.imgur.com/xgG0K7i.png
The first ng-repeat shows correctly the different users, but the second show the same tasks of the first user to the others users in the list.
¿How can i change the parameter to update correctly for the nested ng-repeat?
My Services:
.service('TeamworkPeopleSrvc', function($http, $q){
var deferred = $q.defer();
var TeamworkPeopleSrvc = this;
TeamworkPeopleSrvc.getPeople = function(){
$http.defaults.headers.common['Authorization'] = 'Basic ' + window.btoa('mycustomapikey' + ':' + 'X');
$http({
method: 'GET',
url: 'http://projects.com/people.json',
params: { 'pageSize':'5'},
})
.then(function(response) {
deferred.resolve(response);
});
return deferred.promise;
};
return TeamworkPeopleSrvc;
})
.service('TeamworkTasksSrvc', function($http, $q){
var deferred = $q.defer();
var TeamworkTasksSrvc = this;
TeamworkTasksSrvc.getTasks = function(id){
$http.defaults.headers.common['Authorization'] = 'Basic ' + window.btoa('mycustomapikey' + ':' + 'X');
$http({
method: 'GET',
url: 'http://projects.com/tasks.json' ,
params: { 'id':id, 'getSubTasks':'no', 'pageSize':'10'},
})
.then(function(response) {
deferred.resolve(response);
});
return deferred.promise;
};
return TeamworkTasksSrvc;
})
My Controller
.controller('PeopleCtrl', function ($scope, TeamworkPeopleSrvc, TeamworkTasksSrvc) {
$scope.init = function(){
$scope.peopleObjects();
};
$scope.taskObjects = function(id){
TeamworkTasksSrvc.getTasks(id)
.then(function(response){
$scope.userTasklist = response.data['todo-items'];
});
};
$scope.peopleObjects = function(){
TeamworkPeopleSrvc.getPeople()
.then(function(response){
$scope.userlist = response.data.people;
});
};
$scope.init();
});
and try to init the tasks with the updated user id in the template
<div ng-controller="PeopleCtrl">
<div ng-repeat="person in userlist">
<h3>{{person['id']}} | {{person['first-name']}} {{person['last-name']}}</h3>
<div ng-init="taskObjects(person['id'])">
<div ng-repeat="task in userTasklist">
{{task['responsible-party-id']}} - {{task['content']}}
</div>
</div>
</div>
</div>
Best Regards.
The problem is in your controller code. You are using the same $scope for both loops, which means that each time you call taskObjects(), you are overwritting $scope.userTasklist with a new task list. You should either establish a new scope for each instance within the loop, or you should make $scope.userTasklist an object with properties matching the person.id.
In your controller change:
$scope.taskObjects = function(id){
TeamworkTasksSrvc.getTasks(id)
.then(function(response){
if(!$scope.userTasklist) {
$scope.userTasklist = {};
}
$scope.userTasklist[id] = response.data['todo-items'];
});
};
And then in your view use:
<div ng-controller="PeopleCtrl">
<div ng-repeat="person in userlist">
<h3>{{person['id']}} | {{person['first-name']}} {{person['last-name']}}</h3>
<div ng-init="taskObjects(person['id'])">
<div ng-repeat="task in userTasklist['id']">
{{task['responsible-party-id']}} - {{task['content']}}
</div>
</div>
</div>
</div>
Defective $q.defer Anti-Pattern1
.service('TeamworkPeopleSrvc', function($http, $q){
var deferred = $q.defer();
var TeamworkPeopleSrvc = this;
TeamworkPeopleSrvc.getPeople = function(){
$http.defaults.headers.common['Authorization'] = 'Basic ' + window.btoa('mycustomapikey' + ':' + 'X');
$http({
method: 'GET',
url: 'http://projects.com/people.json',
params: { 'pageSize':'5'},
})
.then(function(response) {
deferred.resolve(response);
});
return deferred.promise;
};
return TeamworkPeopleSrvc;
})
Both services in the code use a defective $q.defer Anti-Pattern. With the deferred object created outside the .getPeople function, the promise will only be resolved once with the first resolve. Subsequent resolves are ignored and the promise always returns the first value. In addition if the XHR has an error, the error information is lost. With errors, the promise never resolves or resolves only with the first fulfilled XHR.
Implemented Without $q.defer
.service('TeamworkPeopleSrvc', function($http, $q){
var TeamworkPeopleSrvc = this;
TeamworkPeopleSrvc.getPeople = function(){
var authHeader = { Authorization: 'Basic ' +
window.btoa('mycustomapikey' + ':' + 'X')
};
var httpPromise = ($http({
method: 'GET',
url: 'http://projects.com/people.json',
headers: authHeader,
params: { 'pageSize':'5'},
})
);
return httpPromise;
};
return TeamworkPeopleSrvc;
});
To implement the service correctly, simply return the promise returned by the $http service. A new promise will be created each time the $http function is invoked and error information will be properly retained.

angularjs XXXService.XXXfunction is not a function

It is my first try writing up a service in AngularJS. I have a service, in which I have a function. When I call this service from my controller, it says XXXService.XXXfunction is not a function.
My Javascript is like,
var sharecycle0_angularfire = angular.module("sharecycle0_angularfire", []);
sharecycle0_angularfire.service("baseHttp", function($http, $q){
self.getFire = function(){
var deferred = $q.defer();
$http({
method: GET,
url: "https://boiling-inferno-1234.firebaseio.com/Cat"
}).then(function(response){
deferred.resolve(response);
},function(response){
deferred.reject(resposne);
});
return deferred.promise;
};
});
sharecycle0_angularfire.controller("angularfirecontroller", function($scope, baseHttp, $window){
$scope.fireClick = function(){
baseHttp.getFire()
.then(
function(response)
{
$("<div/>").text(response).appendTo($("#successData"));
},
function(response)
{
$window.alert("error: "+response);
}
);
};
});
My HTML is like,
<body ng-controller="angularfirecontroller">
<button id="fireClickButton" ng-click="fireClick()">fireClick</button>
<div id="successData"/>
</body>
I expect the service code to run upon my button being hit.
You have some issues here, you are not attaching the function getFire to the service instance, instead you are attaching it to the global variable self. self global variable is generally an alias to window object in many browsers so you are attaching the function to the window and not to the controller instance. Since http already returns a promise you do not need to create a deferred object there, instead just return the result of $http. Apart from that GET needs to be a string value, you are trying to use an undefined variable GET and not "GET". Many a times placing a debug log in relevant areas of the code will help you diagnose the issue.
All you would need is:
sharecycle0_angularfire.service("baseHttp", function($http, $q){
this.getFire = function(){
return $http({
method: 'GET',
url: "https://boiling-inferno-1234.firebaseio.com/Cat"
});
}
});
if you intended to cache this then you should create a local variable and assign this to that.
i.e
sharecycle0_angularfire.service("baseHttp", function($http, $q){
var _this = this; //Or var self = this
_this.getFire = function(){
return $http({
method: 'GET',
url: "https://boiling-inferno-1234.firebaseio.com/Cat"
});
}
});

simple angular service confusion

To put it simply angular services always confuse me and I seem to get them working by trial and error. I'd like to know why in this case data returns undefined.
App module :
var app = angular.module('myApp', ['services']);
Service:
//creating a service module
var appServices = angular.module('services', []);
appServices.factory('Data', function(){
return {message : "I am data"}
});
Controller:
app.controller('firstCtrl',['Data',
function($scope, Data){
//get data from the service
$scope.data = Data;
console.log(Data);
}]);
app.controller('secondCtrl',['Data',
function($scope, Data){
//get data from the service
$scope.data = Data;
}]);
If I console log data I just get "undefined" .
Im just trying to do a simple example to return the object {message:"i am data"}
so that
$scope.data = Data;
then in the view
data.message = "i am data"
Would really appreciate an explanation of why this does not work. Thanks
You're not injecting $scope into the controller. Change it to this:
app.controller('firstCtrl', [
'$scope', // There should be an element of this array for each parameter
'Data',
function($scope, Data){
//get data from the service
$scope.data = Data;
console.log(Data);
}
]);
As you're only injecting the Data service it gets mapped to the $scope parameter of the controller function, and nothing gets mapped to the Data parameter (and since a variable that has not been assigned a value implicitly has the value undefined, you see undefined).
you can use above answer but you can use
app.controller('firstCtrl', function($scope, Data){
//get data from the service
$scope.data = Data;
console.log(Data);
});
this will work fine no need for passing array of services and function in controller as second argument just function will work fine.

Categories

Resources