How to update scope variable value in view after http call? - javascript

I am making my first project using Angularjs 1.4.3.
In my controller I am making a http request, in the success method of this http request I am updating a scope variable. In http call I am getting the latest values but in the view side its not updating the values.
Plunker Link (#rupesh_padhye thanks). (Since it is calling the servlet action, so no data will be shown in Plunker)
app.controller('measuresCtrl', ['$scope', '$modal', '$http', function($scope, $modal, $http) {
$scope.groups = []
$scope.loadAllMeasure = function() {
$http.get("fetchAllMeasure")
.success(function(data) {
console.log("Before insert");
console.log($scope.groups);
$scope.groups = data.measures;
console.log("After insert");
console.log($scope.groups);
})
.error(function() {
});
};
$scope.loadAllMeasure();
$scope.submit = function (form) {
$http({
method: 'POST',
url: 'saveMeasure',
data: {
id: form.id,
name: form.name,
description: form.description
},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function(data, status, headers, config) {
$scope.loadAllMeasure();
}).error(function(data, status, headers, config) {
});
}
})
And whenever I am performing any CRUD operation on measures I am calling a method $scope.loadAllMeasure();. But its not updating the values in the view (jsp) page.
I have tried $scope.$apply method but I am getting Error: $digest already in progress.
When I printed the value for $scope.groups using console.log inside success method, then its showing the latest values.
In my view (jsp) page I am just using ng-repeat function to show all the records in table format.
Code for my view page (minimal code) -
<div ng-repeat="group in groups | orderBy:'name'">
<div>
<input type="checkbox" id="checkbox-{{group.id}}" class="ui-checkbox" /><label for="checkbox-{{group.id}}">{{group.name}}</label>
</div>
<div>{{ group.description}}</div>
<div>
<div class="fa fa-pencil button" data="{{group.id}}" id="{{::elementId}}" ng-click="showEditForm(group.id, $event)"></div>
<div class="fa fa-trash button" data="{{group.id}}" ng-click="deleteGroup(group.id)"></div>
<div class="fa fa-clone button" data="{{group.id}}" id="{{::elementId}}" ng-click="showCloneForm(group.id, $event)"></div>
</div>
</div>
Values in console.log are
Before insert
Object { id=1, description="Measure Description1", name="Demo"}]
And
After Insert
[Object { id=1, description="Measure Description1", name="Demo"}, Object { id=2, description="Description2", name="Demo2"}]
How to update scope variable value in view after http call?

After assigning the new data to a $scope variable call:
$scope.$digest();
This will update the current scopes values
reference here: https://docs.angularjs.org/api/ng/type/$rootScope.Scope

I cant see anything wrong with your example code.
I have created a JSFiddle to try and help you.
The server call has been replaced by a setTimeout function that returns a promise.
Please see JSFiddle https://jsfiddle.net/sjwkbzxa/
Please see example below:
<div data-ng-controller="TestController as vm">
<button data-ng-click="loadAllMeasure()">Load List from Server</button>
<ul>
<li data-ng-repeat="group in groups | orderBy:'name'">
<span>{{group.description}}</span>
</li>
</ul>
</div>
The javascript:
angular.module('application',[]).controller("TestController", ['$scope', '$q', function($scope, $q){
$scope.groups = [{ id:1, description:"Initial List", name:"Demo"}];
$scope.loadAllMeasure = function(){
loadData().then(function(data){
$scope.groups = data;
});
};
function loadData(){
var deferred = $q.defer();
setTimeout(function(){
var data = [{ id:1, description:"Measure Description1", name:"Demo"}, { id:2, description:"Description2", name:"Demo2"}];
deferred.resolve(data);
}, 3000);
return deferred.promise;
}
}]);
Maybe you are missing something on your side that we cant see?

I'm a little late to answer this, but here are my 2 cents:
A simple assignment of the server data (response.data) to a $scope object didnt seem to work for me
$scope.something = response.data //didn't work
So, I returned a promise object from the service into the controller and then use
angular.copy(response.data,$scope.something)
to copy the values returned from the server. You could also pass the $scope.something to the service as a parameter to the function and have angular.copy in the service function as well, but i don't know if it's a good practise to do that.

$scope.loadAllMeasure = function() {
CalltoServer();
};
CalltoServer = function() {
return $http.get("fetchAllMeasure")
.success(function(data) {
$scope.groups = data.measures;
})
.error(function() {
});
}
try this , the success will be after 2 or 3 seconds so i guess inside the event it takes rist to bind

Hey I also faced the same issue and if anyone is still looking, it is caused by change in the $scope variable inside the $http. I think a new $scope is being created inside the success function(some prototypical inheritance stuff).
So make a copy of the variable $scope, something like
var s = $scope;
and then change
s.groups = someData;
Your code:
app.controller('measuresCtrl', ['$scope', '$modal', '$http', function($scope, $modal, $http) {
var s = $scope;
$scope.groups = []
$scope.loadAllMeasure = function() {
$http.get("fetchAllMeasure")
.success(function(data) {
console.log("Before insert");
console.log($scope.groups);
s.groups = data.measures;
console.log("After insert");
console.log($scope.groups);
})
.error(function() {
});
};
$scope.loadAllMeasure();
$scope.submit = function (form) {
$http({
method: 'POST',
url: 'saveMeasure',
data: {
id: form.id,
name: form.name,
description: form.description
},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function(data, status, headers, config) {
$scope.loadAllMeasure();
}).error(function(data, status, headers, config) {
});
}
})

Related

Problems with ng-repeat, $scope, $http

im working with AnuglarJS 1.4.8. I want give out the data with ng-repeat.
I have the following problem and i have no more ideas to solve it. I tried the solutions from AnuglarJS but i doesnt work.
Could someone help me please.
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.4.8/$rootScope/infdig?p0=10&p1=%5B%5D
Service:
.service('database', function ($http) {
self = this;
this.url = 'http://localhost:3001';
this.getPersons = function(cb){
return $http({
method: 'GET',
url: self.url + '/loadperson'
}).success(function (data) {
cb(data);
});
};
});
Controller:
angular.module('myApp')
.controller('personCtrl', function ($scope, database) {
$scope.people = function(){
return{
getAll: function () {
database.getPersons(function (data) {
return data;
// should return a Object(id, name)
});
}
}
};
HTML:
<div ng-repeat="people in people().getAll()">
<p>{{people.name}}</p>
</div>
You are missing the non-blocking way of javascript. Try following, it should work
Controller:
angular.module('myApp')
.controller('personCtrl', function ($scope, database) {
$scope.loadPeoples = function(){
return{
getAll: function () {
database.getPersons(function (data) {
$scope.peoples = data;
// should return a Object(id, name)
});
}
}
};
$scope.loadPeoples();
})
HTML:
<div ng-repeat="people in peoples">
<p>{{people.name}}</p>
</div>
Try that.
Service:
.service('database', function ($http) {
self = this;
this.url = 'http://localhost:3001';
this.getPersons = function(){
return $http({
method: 'GET',
url: self.url + '/loadperson'
});
};
});
Controller:
angular.module('myApp')
.controller('personCtrl', function ($scope, database) {
database.getPerson().success(function(data) {
$scope.people = data;
});
});
HTML:
<div ng-repeat="person in people">
<p>{{person.name}}</p>
</div>
You should also be aware that you shouldn't return each time a NEW array for iterating. Otherwise angular will keep calling that function for retrieving a "stable" value for the array.
You've made a common error in javascript when running asynchronous queries. The pattern goes:
function outerFunction() {
invokeInnerFunction(function() {
return 3;
}
}
What does outerFunction() return? An error is to think it returns 3, but the answer is actually that outerFunction doesn't return anything.
Likewise, in your example getAll isn't actually returning anything; it's just calling an asynchronous method. This asynchronous method invoked $http, which triggers a digest loop which will result in getAll being called again, and so on for ever. Be thankful that angular can detect this problem.
You only want to call the database query once on startup, and initialize the list of people. Simply store this list in a variable so it won't query the database again on the next digest loop.
angular.module('myApp')
.controller('personCtrl', function ($scope, database) {
$scope.allPeople = [];
database.getPersons(function(data) {
$scope.allPeople = data;
});
};
An then for your HTML
<div ng-repeat="people in allPeople">
<p>{{people.name}}</p>
</div>
Much simpler.
Have you tried making a separate function to fetch the entities from the data base, then put this data in a variable, that you then will pass to the ngRepeat ?
your controller
angular.module('myApp')
.controller('personCtrl', function ($scope, database) {
$scope.people = [];
$scope.getPeople = function(){
return{
getAll: function () {
database.getPersons(function (data) {
$scope.people = data;
return;
// should return a Object(id, name)
});
}
}
//load the list of people
$scope.getPeople();
};
your view
<div ng-repeat="person in people">
<p>{{person.name}}</p>
</div>

How to update model using angularjs, Django,Django rest framework

I have such json representation of a post by its id:
http://127.0.0.1:8000/update/1?format=json
{"title": "about me", "content": "I like program", "created": "2014-11-29T18:07:18.173Z", "rating": 1, "id": 1}
I try to update rating by button click:
<button ng-click="click(post.id)">Click me</button>
I have such javascript code:
<script>
var demoApp = angular.module('demoApp',['ngResource']);
demoApp.controller( 'AllPosts', function ($scope, $http)
{
$http.get('/blogpost/?format=json').success(function(data,status,headers,config)
{
$scope.posts = data.results;
$scope.predicate = '-title';
$scope.click = function(post_id, $resource){
var Post = $resource('/update/:PostId ',{PostId:post_id,format:'json'} );
post = Post.get({PostId:post_id}, function() {
post.rating = post.rating+ 1 ;
post.$save();
});
};
}).error(function(data,status,headers,config)
{} )
;})
</script>
Peharps i have mistake because in json i have a single object. But i dont really know
Besides i have such view to have a json by certain post by its id:
class UpdateModel(generics.RetrieveUpdateDestroyAPIView):
lookup_field = 'id'
queryset = BlogPost.objects.all()
serializer_class = BlogPostSerializer
permission_classes = (AllowAny,)
A quick tidy up of your script tag shows that you are only defining the function click if the http call was successful.
I would suggest moving the definition of the click method outside of the success callback.
You may also be running into a race condition that the click function has not been defined before clicking the actual button. Regardless you will want to move that function definition to where the controller is actually created.
Suggested edits (moved click definition outside of http call response):
var demoApp = angular.module('demoApp', ['ngResource']);
demoApp.controller('AllPosts', function($scope, $http, $resource) {
$scope.click = function(post_id) {
var Post = $resource('/update/:PostId ', {
PostId: post_id,
salutation: 'json'
});
post = Post.get({
PostId: post_id
}, function() {
post.rating = post.rating + 1;
post.$save();
});
};
$http.get('/blogpost/?format=json').success(function(data, status, headers, config) {
$scope.posts = data.results;
$scope.predicate = '-title';
}).error(function(data, status, headers, config) {});
})
Updates:
Injected $resource into the controller
Removed $resource from click function params

$scope in AngularJS returns nothing in ng-repeat

I am trying to return an object, taht I populate in a forEach loop, with angulars $scope from a controller, but when I try to loop it out with ng-repeat I get no result.
When i console.log the object I get the expected result
But when I try to return it with $scope and show it with ng-repeat I get no results what so ever.
Here is my controller
myAppControllers.controller('musicCtrl', ['$scope', '$http', function($scope, $http) {
var i = 0,
playlists = {};
// Get the playlists from soundcloud
$http({ method: 'GET', url: 'http://api.soundcloud.com/users/gimle-sound-tjek/playlists.json?client_id=c2dfe07de1d18d689516884ce22b7aae' }).
success(function(data) {
data.forEach(function() {
// Populate the object
playlists[i] = {
"title" : data[i].title,
"permalink": data[i].permalink,
"genre": data[i].genre
}
i++;
});
console.log(playlists);
$scope.playlists;
}).
error(function() {
$scope.playlists = '';
});
}]);
My ng-repeat looks like this
<div ng-repeat="playlist in playlists">
<h3>{{ playlist.title }}</h3>
...
I am expecting that is has something to do with the way I send the object back with $scope.playlists?
First of all maybe use push instead this i++ fun.
You push those playlist entries into the playlist variable outside the scope.
myAppControllers.controller('musicCtrl', ['$scope', '$http', function($scope, $http) {
$scope.playlists= [];
// Get the playlists from soundcloud
$http({ method: 'GET', url: 'http://api.soundcloud.com/users/gimle-sound-tjek/playlists.json?client_id=c2dfe07de1d18d689516884ce22b7aae' }).
success(function(data) {
data.forEach(function(entry) {
// Populate the object
$scope.playlists.push({
"title" : entry.title,
"permalink": entry.permalink,
"genre": entry.genre
});
//OR: $scope.playlists.push(entry);
});
}).
error(function() {
$scope.playlists = '';
});
}]);
What if you try $scope.playlists = [] instead of var playlist = {}

How to write an angularJs Controller to GET Rest Data from Parse.com

See solution below:
I'm trying to connect to a Parse.com Rest backend and display data from object values.
HTML (I put several angular calls to be sure to catch output):
<div ng-controller="MyController">
<p>{{item}}<p>
<p>{{items}}<p>
<p>{{item.firstName}}<p>
<p>{{data}}<p>
</div>
JAVASCRIPT rest:
function MyController($scope, $http) {
$scope.items = [];
$scope.getItems = function() {
$http({method : 'GET',url : 'https://api.parse.com/1/classes/Professional/id', headers: { 'X-Parse-Application-Id':'XXXX', 'X-Parse-REST-API-Key':'YYYY'}})
.success(function(data, status) {
$scope.items = data;
})
.error(function(data, status) {
alert("Error");
});
};
}
This won't work, it does strictly nothing, not even a message in the console.
I know the rest call got the correct credential, as I'm able to get object content returned when I test it with a rest tester program. Maybe the URL should not be absolute ?
Any clue is very welcome, i've spent DAYS on that.
SOLUTION:
Thanks to the help of people answering this thread, I was able to find the solution to this problem so I just wanted to contribute back:
Get Json object data from Parse.com backend, pass it authentification parameters:
function MyController($scope, $http) {
$scope.items = [];
$scope.getItems = function() {
$http({method : 'GET',url : 'https://api.parse.com/1/classes/Professional', headers: { 'X-Parse-Application-Id':'XXX', 'X-Parse-REST-API-Key':'YYY'}})
.success(function(data, status) {
$scope.items = data;
})
.error(function(data, status) {
alert("Error");
});
};
Notice that ' ' necessary arround header key object values. Those ' ' are not necessary around method and url keys.
Template that list all 'firstName' of each object:
<div ng-controller="MyController" ng-init="getItems()">
<ul>
<li ng-repeat="item in items.results"> {{item.firstName}} </li>
</ul>
</div>
Notice: "item in items.results". "results" is necessary because the return value is a JSON object that contains a results field with a JSON array that lists the objects. This could save you some headache.
Also notice "ng-init": if you don't put that, or any other form of call to the getItem(),then nothing will happen and you will be returned no error.
That was my first try of Angularjs, and i'm already in love ^^.
Based in your request the controller should be:
HTML
<div ng-controller="MyController">
<button type="button" ng-click="getItems()">Get Items</button>
<ul>
<li ng-repeat="item in items"> item.firstName </li>
</ul>
</div>
JS
function MyController($scope, $http) {
$scope.items = []
$scope.getItems = function() {
$http({method : 'GET',url : 'https://api.parse.com/1/classes/Users', headers: { 'X-Parse-Application-Id':'XXXXXXXXXXXXX', 'X-Parse-REST-API-Key':'YYYYYYYYYYYYY'}})
.success(function(data, status) {
$scope.items = data;
})
.error(function(data, status) {
alert("Error");
})
}
}
Just a little update to the newer versions of Angular (using .then since version 1.5):
myApp.controller('MyController', function($scope, $http) {
$scope.items = []
$http({
method: 'GET',
url: 'https://api.parse.com/1/classes/Users',
headers: {'X-Parse-Application-Id':'XXXXXXXXXXXXX', 'X-Parse-REST-API-Key':'YYYYYYYYYYYYY'}
})
.then(function successCallback(response) {
alert("Succesfully connected to the API");
$scope.items = data;
}, function errorCallback(response) {
alert("Error connecting to API");
});
});
var app = angular.module("app",[]);
app.controller("postcontroller", function($scope, $http){
$scope.getAllProjects = function() {
var url = 'https://reqres.in/api/products';
$http.get(url).then(
function(response) {
$scope.projects = response.data.data;
},
function error(response) {
$scope.postResultMessage = "Error with status: "
+ response.statusText;
});
}
$scope.getAllProjects();
});
<div ng-app="app">
<div ng-controller="postcontroller">
<div class="panel-body">
<div class="form-group">
<label class="control-label col-sm-2" for="project">Project:</label>
<div class="col-sm-5">
<select id="projectSelector" class="form-control">
<option id="id" ng-repeat="project in projects"
value="{{project.id}}">{{project.name}}</option>
</select>
</div>
</div>
</div>
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>

AngularJS model is populated in javascript but empty on the page

I've got this code...
Agencyapp.factory('AgencyData', function ($http, $log) {
return {
getAgencies: function(successcb){
$http({ method: 'GET', url: 'http://localhost/MappingServicesWebAPI/api/mapping' }).
success(function(data){
successcb(data);
}).
error(function(data){
$log.warn(data, status, headers, config);
})
}
}
});
Which gets data from a WebAPI. The $scope.Agencies model gets populated with an AgencyList array. When I try to use that array...
<div ng-controller="AgenciesCtrl">
<select ng-model="Agencies">
<option>Select Agency</option>
<option ng-repeat="A in Agencies" >{{A.AgencyList.AgencyName}}</option>
</select>
{{Agencies.AgencyList}}
</div>
It's empty...can someone help me with what I might be doing wrong?
Here's the controller, sorry I thought I included it...
Agencyapp.controller('AgenciesCtrl', function AgenciesCtrl($scope, AgencyData) {
AgencyData.getAgencies().then(function (rtnAgencies) {
$scope.Agencies = rtnAgencies;
});
});
I tried to post a picture of the populated $scope object but I don't have enough reputation points...
It Looks like this(each indent is a nested object)...
$scope.Agencies
[prototype]
AgencyList[]
[0]
[prototype]
AgencyID -10168
AgencyName "#1 Insurance Agency"
If I hard code data...
function AgenciesCtrl($scope, AgencyData) {
$scope.Agencies = [
{
AgencyID: 'Test One',
AgencyName: 'Agency Test 1'
},
{
AgencyID: 'Test Two',
AgencyName: 'Agency Test 2'
}];
};
It Works
If I hard code data inside the function call
function AgenciesCtrl($scope, AgencyData) {
AgencyData.getAgencies().then(function (rtnAgencies) {
$scope.Agencies = [
{
AgencyID: 'Test One',
AgencyName: 'Agency Test 1'
},
{
AgencyID: 'Test Two',
AgencyName: 'Agency Test 2'
}];
});
};
It doesn't work
I haven't seen one good example of using data from a web api...all examples I have seen hard code data, what's the point in that?
First, remove ng-model="Agencies" from your <select> element. You dont want to bind your select element to the same object that you are running an ng-repeat on. Try something like <select ng-model="selectedAgency" > instead.
Second, I suggest utilizing angular's deferred API to return a promise, which will then be resolved with the value of the data returned from the server, when it is finished:
Agencyapp.factory('AgencyData', function ($http, $log, $q) {
return {
getAgencies: function(successcb){
var deferred = $q.defer();
$http({ method: 'GET', url: 'http://localhost/MappingServicesWebAPI/api/mapping' }).
success(function(data){
deferred.resolve(successcb(data)); //I dont know what successcb() does
}).
error(function(data){
deferred.reject(data);
$log.warn(data, status, headers, config);
})
return deferred.promise;
}
};
});
In your controller, you would then do something like this:
AgencyData.getAgencies().then(function(data) {
$scope.Agencies = data;
});
As soon as the getAgencies() function finishes getting the data, the $scope.Agencies object will be updated with the resulting data.
It turns out I had my...
<div ng-controller="AgenciesCtrl">
<select ng-model="Agencies">
<option>Select Agency</option>
<option ng-repeat="A in Agencies" >{{A.AgencyList.AgencyName}}</option>
</select>
{{Agencies.AgencyList}}
</div>
Inside a that was controlled by a Javascript Library called Slidebox.js.
Once I removed Slidebox.js everything worked correctly.

Categories