Data bind works only on second click event - angularjs

I have a click event to call the AngularJS function which retrieves the data from SQL and return to the ajax call.
My problem is the data which is retrieved binds with ng-repeat only on the second click event.Here is my code,
`
(function (app) {
app.controller("OnvioController", function ($scope,$http, OnvioService) {
$scope.retData = [];
$scope.getResult = function () {
var serviceURL =window.location.origin+ '/Datafetching/dataFetch';
$.ajax({
type: "POST",
url: serviceURL,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data, status) {
$scope.retData = data;
},
error: function (status) {
}
});
}
});
}(angular.module("OnvioModule")));
`

Do not use $.ajax in angularJS.
You can do this by $http.get
I haven't tried it my self right now. but it should work in your case.
(function (app) {
app.controller("OnvioController", function ($scope,$http, OnvioService) {
$scope.retData = [];
$scope.getResult = function () {
var serviceURL =window.location.origin+ '/Datafetching/dataFetch';
$http.get(serviceURL).success( function(response) {
$scope.retData = response;
});
}
});
}(angular.module("OnvioModule")));
refer this document for more details

Use $http.post instead of $.ajax.
If you still want to use $.ajax add a $scope.$apply() in your success function.
This will trigger angular loop to search for changes outside of his context. This is because $.ajax is executing outside of angular stuff.

Add a $scope.$apply() in your success function.

Related

How to assure that one out of 2 functions run first

I have 2 functions bindclub() and displayevent(). I want to assure bindclub() to run first always.I have also tried to put both the functions in ng-init but it also does not assured to run bindclub() first
angular.module('app', []).controller("EventCtrl",EventController);
EventController.$inject = ["$scope", "$http", "$window"];
function EventController($scope, $http, $window) {
$scope.bindclub = function () {
$http({
url: '/Master/bindclub',
method: 'post',
}).then(function (response) {
debugger
$scope.clubidname = response.data;
}, function () { alert("Error in binding club"); });
}
$scope.displayevent = function () {
$http({
url: '/Master/displayevent',
method: 'post',
}).then(function (response) {
alert('Displayed');
}, function () { alert('Error in display event'); });
}
$scope.bindclub ();
$scope.displayevent ();
}
Is the second event dependent on the first event? If yes then you may set it as a callback event of the first event, to ensure that it is triggered on the success of the first event.
use callback function wait until bindclub function executing and then start displayevent function
angular.module('app', []).controller("EventCtrl", EventController);
EventController.$inject = ["$scope", "$http", "$window"];
function EventController($scope, $http, $window) {
$scope.bindclub = function(callback) {
$http({
url: '/Master/bindclub',
method: 'post',
}).then(function(response) {
debugger
$scope.clubidname = response.data;
callback() // callback function
}, function() {
alert("Error in binding club");
callback()// callback function
});
}
$scope.displayevent = function() {
$http({
url: '/Master/displayevent',
method: 'post',
}).then(function(response) {
alert('Displayed');
}, function() {
alert('Error in display event');
});
}
$scope.bindclub(function() {
$scope.displayevent(); // this execute after bindclub fucntion
});
}
The function bindclub is indeed being run before displayevent. But these two functions themselves make http calls which have callbacks. There is no guarantee to have the callbacks executed in the order you want.
The only work around I see is to call the other function inside of the callback in bindclub.
The other way is for you to chain the callbacks.
You can attach displayEvent to a custom event that is triggered inside the bindEvent callback.
Check out this SO post for example on how to do this.
Return the promise and then chain them:
$scope.bindclub = function () {
//vvvv RETURN httpPromise
return $http({
url: '/Master/bindclub',
method: 'post',
}).then(function (response) {
debugger
$scope.clubidname = response.data;
}, function () { alert("Error in binding club"); });
}
//CHAIN them
$scope.bindclub()
.then(function () {
$scope.displayevent();
});
Since the $http service returns a promise, the second operation can be chained from the first operation with the .then method of the first promise.

How to make a loading (spin) while requesting to server by $http on angularJS

$http({
method: 'POST',
url: '',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: {
}
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
if(response.data == 'true'){
swal("Good job!", "New case has been created", "success");
}
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
I want to show a progress bar or spin on bootstrap while http request on angularjs
Sugessting you to use this angular-loading-bar
Steps
Include the script references and css as mentioned in the above
github, you can use cdn as well as mentioned.
Add these two functions in your controller
$scope.start = function() {
cfpLoadingBar.start();
};
$scope.complete = function () {
cfpLoadingBar.complete();
}
Include the 'angular-loading-bar', 'ngAnimate' as dependencies.
Add the below code for the app configurations
If you are looking for the progress bar
app.config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) {
cfpLoadingBarProvider.includeSpinner = false;
}])
If you are looking for a spinner
app.config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) {
cfpLoadingBarProvider.includeSpinner = true;
}])
Finally, In your $http request call the $scope.start() function and in your success method call the $scope.complete()
LIVE DEMO
A simple way:
html:
<div class="spinner" ng-show="loading"></div>
js :
$scope.loading = true
$http.post(...).then(function(response){
$scope.data = response.data // or whatever you needs...
$scope.loading = false
},function(){
$scope.loading = false
console.log("error")
})
If you want to generalize, you can also have a look to http interceptor : https://docs.angularjs.org/api/ng/service/$http#interceptors

Ajax in AngularJS Service

Created an Angular Service:
calculator_app.service('FillOpportunity', function () {
this.fill_opportunity = function (path,scope) {
$.ajax({
url: 'opportunitycalculator/calculator/GetProducts?idstring=' + path,
type: "GET",
cache: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data)
{
scope.opportunity_data = data;
scope.$apply();
},
error: function () {
}
});
};
});
Called the service on ng-change of a dropdown:
FillOpportunity.fill_opportunity($scope.result_path,$scope);
The scope.opportunity_data is binded to the select in UI:
<select id="seloppurtunityproducts" name="selproducttype" multiple="" style="height:300px" ng-model="opportunity_products" ng-options="a for a in opportunity_data"></select>
On ng-Change, Ajax is called when I check in Network of Chrome, but the value is not updated in the select box.
Any inputs?
Don't use jQuery's ajax. Use the built in $http. Using $http automatically begins the digest cycle of angular's builtin compiler. If you must use jquery... then you'd have to call $scope.$apply(); every time there is a data change.
Service:
calculator_app.factory("calcService", ["$http", function($http) {
return {
getItem: function(url, items) {
return $http.get(url,
// query string like { userId: user.id } -> ?userId=value
{ params: items });
}
}
}]);
Inject the service into your controller and use:
calculator_app.controller("MainCtrl", ["calcService", "$scope", function(calcService, $scope) {
$scope.opportunity_data = [];
var payload = {
idstring: path
};
//call the service
calcService.getItem('path/to/calc/api', payload).then(function(response) {
$scope.opportunity_data = response.data;
}).catch(function(response) {
alert('error' + response.data);
});
}]);

AngularJS Request payload is always empty

I have created a Angular resource that sends POST data to a web service. Here is my factory:
appServices.factory('Foo', function($resource) {
var data = $resource(
'http://localhost:3000/api/v1/foo.json',
{},
{
'save': {
method: 'POST',
cache: false
}
});
return data;
});
Here's my Controller:
appControllers.controller('FooCtrl', function($scope, Foo, $location) {
$scope.memberData = {};
$scope.create = function() {
var member = new Foo();
member.$save( {}, { bar: bar });
$location.url("/");
};
});
When I submit the form in my client, it returns a 500 status. Looking into Firebug, I can see that my POST data payload always remains empty for some reason.
What am I doing wrong?
PS. I've added this to my config: $httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
If you want to issue a POST request to the member resource, you can use save() (without the $) and pass in your body as the first argument:
Foo.save({bar: 'bar'}, function () {
// Callback
});
However, when creating a new resource instance, it is augmented with a $save() method (note the $). When you invoke this method, the instance itself is sent as the body. So you should change your code to:
var member = new Foo();
member['bar'] = 'bar';
member.$save(function () {
// Callback
});
Check this article for more information.

AngularJS - scope variable does not get updated from method

I'm totally new to AngularJs and I have this problem I do not understand. I have two methods. The first one takes some data from a webservice and puts in in a variable defined in the scope. But when I want to use that variable in the second method it is undefined. Can someone help me understand why this is happening and provide a solution?
var myApp= angular.module( "myApp", [] );
myApp.controller("myAppController",
function( $scope ) {
$scope.getAll = function(){
$.ajax({
type: "GET",
dataType: "jsonp",
contentType: "application/json; charset=utf-8",
url: ..something...,
success: function (parameters) {
$scope.profiles = angular.copy(parameters); <-- correct data is returned
$scope.$apply();
},
error: function () {
alert("Error calling the web service.");
}
});
}
$scope.getCategories = function(){
var all = $scope.profiles; <-- At this point profiles is empty
...
}
$scope.getAll();
$scope.getCategories();
}
Use the $http service and promises:
$scope.profiles = $http.jsonp(url).then(function(r){ return r.data; });
$scope.categories = $scope.profiles.then(function(profiles) {
var params = { }; // build url params
return $http.jsonp(url, { params: params }).then(function(r){ return r.data; });
});
When you call getCategories(), getAll() hasn't finished yet, which is why profiles is empty. There are several ways to solve this. The best way would be to use promises the built-in $http service.
If you prefer to use jQuery, you can add a watcher on the profiles variable and only when it's populated run the getCategories().
Something like this should work:
$scope.getAll = function(){
$.ajax({
type: "GET",
dataType: "jsonp",
contentType: "application/json; charset=utf-8",
url: ..something...,
success: function (parameters) {
$scope.profiles = angular.copy(parameters); <-- correct data is returned
$scope.$apply();
},
error: function () {
alert("Error calling the web service.");
}
});
}
$scope.getCategories = function(){
var all = $scope.profiles;
}
// Wait for the profiles to be loaded
$scope.watch('profiles', function() {
$scope.getCategories();
}
$scope.getAll();
There is no guarantee that getAll has completed before getCategories is invoked, since it is an asynchronous request. So if you want to sequentially invoke getAll and getCategories, you should invoke getCategories inside the success callback of getAll. You could also look into promises for a neater way of chaining asynchronous callbacks (I assume you're using jQuery since you're calling $.ajax).
...
<snipped some code>
success: function(parameters) {
// snipped more code
$scope.getCategories();
}
(and if you're using jQuery promises)
$.ajax(ajaxCallOneOpts).then($.ajax(ajaxCallTwoOpts));
Neither are very "Angularish" though, so you might want to look into some of the provided services for working with http/rest resources instead of using jQuery.
Why are you using a jQuery ajax request in angular? If you write jQuery style code and wrap it angular, you're going to have a bad time...
Here is an angularised version:
myApp.controller("myAppController",
function( $scope, $q, $http ) {
$scope.getAll = function(){
var deferred = $q.defer();
$scope.profiles = deferred.promise;
$http.jsonp('your url').then(function(data) {
deferred.resolve(data);
});
});
$scope.getCategories = function(){
$q.when($scope.profiles).then(function(profiles) {
... <-- At this point profiles is populated
});
}
$scope.getAll();
$scope.getCategories();
}

Resources