unable to use $q and promise - javascript

I want to use the variable StatusASof to display data in the inserthtml function as below.
App.controller("SS_Ctrl", function ($scope, $http, $location, $window, $sce, $q) {
var ShiftDetails = [];
function getMAStatusASof(Id) {
var defer = $q.defer();
$http({
method: 'GET',
url: 'http://xx/api/Sxxx/GetMAStatusASof',
params: { Id: Id }
}).then(function successCallback(response) {
StatusASof = response.data;
alert("getMAStatusASof : " + StatusASof); --> Got data from API here in this alert.
defer.resolve(response);
}, function errorCallback(response) {});
}
function insertHtml(dates, ShiftDetails, Id) {
// var promise = getMAStatusASof(Id); promise.then(
var defer = $q.defer();
getMAStatusASof(Id);
alert(StatusASof); --> alert says empty here
defer.resolve();
var Content;
Content = '<table class="clsTable"> <tr> <td rowspan="2">Cases ' + $scope.StatusASof + ' </td> <td rowspan="2">Total</td> ';
for (var i = 0; i <= 6; i++) {
if (i == daySeq - 1) {
Content = Content + '<td colspan="3" style="background-color:red"> {{dates[ ' + i + ']}} </td> ';
}
}
}
but $scope.StatusASof is undefined while displaying the result. Looks like $q.defer is not working for me.
How can I continue the execution of code after getting data only from the getMAStatusASof(Id);
Can somebody help here.

Update
you need to return defer.promise;
function getMAStatusASof(Id) {
var defer = $q.defer();
$http({
method: 'GET',
url: 'http://xx/api/Sxxx/GetMAStatusASof',
params: { Id: Id }
}).then(function successCallback(response) {
StatusASof = response.data;
alert("getMAStatusASof : " + StatusASof); --> Got data from API here in this alert.
defer.resolve(StatusASof);
}, function errorCallback(response) {
deferred.reject(false);
});
return defer.promise;
}
and the you can use this function like :
getMAStatusASof(Id).then(function(res){
if(res){
$scope.StatusASof = res;
}
})

No need to use $q.defer() here...
Just do
function getMAStatusASof(Id) {
return $http({
method: 'GET',
url: 'http://xx/api/Sxxx/GetMAStatusASof',
params: { Id: Id }
})
.then(function successCallback(response) {
return response.data;
})
.catch(function errorCallback(response) {
return null; //Effectively swallow the error an return null instead.
});
}
Then, use
getMAStatusASof(Id).then(function(result) {
console.log(result);
});
//No .catch, as we've caught all possible errors in the getMAStatusASof function
If you really would like to use $q.defer(), then the function would need to return defer.promise, like Jazib mentioned.
But as I said, since $http already returns a promise, doing the whole $q.defer() + return defer.promise thing is superfluous.
Instead, use that construction only when the thing you need to wrap isn't returning a promise on its own. E.g when you open a bootbox modal and want to be informed of when the user clicked the close button
function notifyMeOfClosing() {
var deferred = $q.defer();
bootbox.confirm("This is the default confirm!", function(result){
if(result) {
deferred.resolve();
}
else {
deferred.reject();
}
});
return deferred.promise;
}

Unable to update #Daniël Teunkens post with following code(from "}" to ")"). So adding as new answer.
getMAStatusASof(Id).then(function(result) {
// your code here. your HTML content.
....
console.log(result);
})
It will work hopefully.

Related

How i can execute a callback function inside a callback function in angularjs

I have two callback functions i want to execute one inside the other one,
heres the first one:
dealer.MeasuringUnit= function () {
// alert("ss");
var url = servername+'admin/measure/getMeasurings';
// var url = 'http://localhost:8080/getFournisseurs';
//$scope.startSpin('spinner-3');
console.log("Inside getAutocarsActiveTrue " + url);
function onSuccess(response) {
console.log("+++++getAutocarsActiveTrue SUCCESS++++++");
if (response.data.success != false) {
console.log("Inside getAutocarsActiveTrue response..." + JSON.stringify(response.data));
var measuring=response.data.data;
//alert(JSON.stringify($scope.mapOptions));
var elm=angular.element(document.querySelector('#measuring'));
//elm.html("");
for(var i=0;i<measuring.length;i++) {
var checkId = measuring[i].id;
var label = measuring[i].label;
// alert(checkId);
dealer.getMeasurByUnitId(checkId);
//alert("ko");
elm.append($compile(
'<label class="control-label">'
+ label
+ '</label>'
+'<select>'
+ '<option ng-repeat="x in units">{{x.label}}</option>'
+'</select><br/>'
)($scope));
}
//console.log($scope.countries);
} else {
alert("failure");
}
// $scope.stopSpin('spinner-3');
};
function onError(response) {
console.log("-------getAutocarsActiveTrue FAILED-------");
//$scope.stopSpin('spinner-3');
console.log(response.data);
console.log("Inside getAllBooks error condition...");
};
//----MAKE AJAX REQUEST CALL to GET DATA----
ajaxServicess.getData(url,"admin","admin", 'GET', '').then(onSuccess, onError);
};
the second one is :dealer.getMeasurByUnitId(checkId)
dealer.getMeasurByUnitId = function (id) {
var url = servername+'admin/unite/getMeasuringByUnit/';
// var url = 'http://localhost:8080/getFournisseurs';
//$scope.startSpin('spinner-3');
console.log("Inside getAutocarsActiveTrue " + url);
function onSuccess(response) {
console.log("+++++getAutocarsActiveTrue SUCCESS++++++");
if (response.data.success != false) {
console.log("Inside getAutocarsActiveTrue response..." + JSON.stringify(response.data));
isGetUnitDone=true;
$scope.units=response.data.data;
console.log($scope.units);
isGetUnitDone=true;
// alert("ass");
} else {
alert("failure");
}
// $scope.stopSpin('spinner-3');
};
function onError(response) {
console.log("-------getAutocarsActiveTrue FAILED-------");
//$scope.stopSpin('spinner-3');
console.log(response.data);
console.log("Inside getAllBooks error condition...");
};
//----MAKE AJAX REQUEST CALL to GET DATA----
ajaxServicess.getData(url,"admin","admin", 'GET', id).then(onSuccess, onError);
};
the second one return an object deponds pn an id return from the from function, but the problem is, in the final result, the select box displays just the last record returned from the second function, how to fix this problem?

AngularJS insert data twice to database

I am trying to insert data to database through angularJS but the data inserted twice.. I have tried to use ngRoute but still I face the same problem.
app.js
var app = angular.module("addDepApp", []);
app.controller('insertDepCtl', function($scope, $http) {
var isSend = false;
$scope.$on('newuser', function(event, data){
load(true);
});
var load = function(isEvent){
if($scope.$parent.newuser != null){
isSend = true;
}
};
load();
$scope.insertDepartment = function () {
console.log("called insertDepartment");
if (isSend == true){
$scope.newuserSend = {'org_id': $scope.$parent.newuser.org_id, 'dep_name': $scope.department};
$http.post("http://192.168.1.12:8888/XXXX/XXX/insertDep.php/",$scope.newuserSend)
}
}
});
add.html
<body ng-app="addDepApp">
<div class="12u$" ng-controller="insertDepCtl">
<input type="button" value="تسجيل" class="special" id="signup" ng-click="insertDepartment()"/>
</div>
</body>
Remove ng-controller="insertDepCtl" from your html code, your router injects this for you. Right now, you're calling everything twice
I have changed the code to this and now it works fine!!
$scope.insertDepartment = function () {
if (isSend == true) {
var request = $http({
method: "post",
url: "http://192.168.1.106:8888/XXXX/XXX/insertDep.php/",
data: {'org_id': $scope.$parent.newuser.org_id, 'dep_name': $scope.department},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
}
}

Call a function to update some variables

I have a collection lines i get from ajax call and i use ng-repeat and for each item line the property line.date need some modification before to be displed
the problem is that I don't know how to call the function to make the modification ?
I try data-ng-init and ng-init the function is called but the variables are not updated !
Html code
<div ng-controller="lineController" data-ng-init="loadLines()">
<div ng-repeat="line in lines">
...
<div data-ng-init="loadDates(line.date)">
...
{{ leftDays}}
</div>
</div>
</div>
Js code :
var app = angular.module("searchModule", []);
app.controller("lineController", function ($scope, $http)
{
// LOAD LINES AJAX
$scope.loadLines = function () {
$http({method: 'GET', url: '..'}).success(function(data) {
angular.forEach(data.content, function(item, i) {
$scope.lines.push(item);
});
});
};
$scope.loadDates = function (date) {
// complex updating of date variable
....
$scope.leftDays = ...;
};
});
Why not manage each line in you angular.forEach?
Like this :
$http({method: 'GET', url: '..'}).success(function(data) {
angular.forEach(data.content, function(item, i) {
//Do stuff to item here before pushing to $scope.lines
//item.date = new Date(item.date) blah blah
$scope.lines.push(item);
});
});
If, you want line.date to be displayed in a different way in you html, and dont want to modify the actual data, why not use a $filter for that?
Like this :
<span ng-repeat="line in lines">{{line.date|yourCustomFilter}}</span>
I think you don't need to do this in this way. You can do this as follows;
$scope.loadLines = function () {
$http({method: 'GET', url: '..'}).success(function(data) {
angular.forEach(data.content, function(item, i) {
$scope.lines.push(item);
});
$scope.lines.map(function(line) {
// here is to modify your lines, with a custom
line.date = $scope.loadDates(line.date);
return line;
})
});
};
By the way, I think you can modify your ajax loading function with this;
$scope.loadLines = function () {
$http({method: 'GET', url: '..'}).success(function(data) {
$scope.lines = data.content.map(function(line) {
// here is to modify your lines, with a custom
line.date = $scope.loadDates(line.date);
return line;
})
});
};
And if you don't need to use loadDates function in view, you don't need to set this function to $scope. You can set this function with just var. Then you can use that function like; loadDates(...) instead of $scope.loadDates(...).
If you don't have to update that $scope.lines variable, you don't need to use .map for this. You can update that function as follows;
$scope.loadLines = function () {
$http({method: 'GET', url: '..'}).success(function(data) {
$scope.lines = data.content;
angular.forEach($scope.lines, function(line) {
// here is to modify your lines, with a custom
$scope.loadDates(line.date);
})
});
};

angularjs call function from html return value

I'm new to AngularJS.
I want to call a function from html.
<td>
{{getComponentSubtype(component.ID)}}
</td>
However, the function calls a webapi and waits for a callback. How do i get the data to show up in the html?
function getComponentSubtype(componentId) {
apiService.get('/api/components/' + componentId + '/componentSubtype', config,
getComponentSubtypeCompleted,
getComponentSubtypeFailed);
}
function getComponentSubtypeCompleted(result) {
$scope.ComponentSubtype = result.data;
//////I WANT TO RETURN $scope.ComponentSubtype.Name//////
}
call the function from HTML and once callback is received store its value in a JSON object which can be printed in HTML. Meanwhile show a loading message in UI
HTML:
{{ getComponentSubtype(component.ID) }}
<td ng-if="componentsSubType[component.ID] != null">
{{ componentsSubType[component.ID] }}
</td>
<td ng-if="componentsSubType[component.ID] == null">Loading Component ...</td>
Controller:
function getComponentSubtype(componentId) {
apiService.get('/api/components/' + componentId + '/componentSubtype', config,
function(result) {
if ($scope.componentsSubType == null) {
$scope.componentsSubType = {};
}
$scope.componentsSubType[componentId] = result;
},
function() {
if ($scope.componentsSubType == null) {
$scope.componentsSubType = {};
}
$scope.componentsSubType[componentId] = "Load Failed";
});
}
Note: I have assumed that in HTML you are getting component from a loop (ng-repeat)
in your HTML ...
<td>{{myvariable}}</td>
in your controller ...
angular.module('yourApp').controller('ControllerName', function($scope, apiService) {
$scope.myvariable = 'please wait';
function initComponent(id) {
apiService.get('/api/components/' + id + '/componentSubtype').then(function(response) {
$scope.myvariable = response;
}).catch(function(failedResponse) {
// handle failure here
console.log('oops', failedResponse);
});
}
initComponent(500);
});
This is quite likely not ideal, but I would need to know more about your code for a better solution.
You could use an object to store the types and access that in your template:
<td>{{ componentSubtypes[component.id] }}</td>
Call getComponentSubtype for each component id:
$scope.componentSubtypes = {};
components.forEach(function(component) {
getComponentSubtype(component.id);
});
function getComponentSubtype(componentId) {
apiService.get('/api/components/' + componentId + '/componentSubtype', config,
getComponentSubtypeCompleted(componentId),
getComponentSubtypeFailed);
}
// Using a closure here for the id
function getComponentSubtypeCompleted(id) {
return function(result) {
$scope.componentSubTypes[id] = result;
// ...
}
}

Passing data from Service AngularJS

Dear all I am having trouble with the scope of my $scope or how should I put it.
I am retrieving the data from my Service successfully but I´m having trouble with accessing $scope.players and $scope.tournament and I think it has something to do with being inside the service call. If I console.out() inside the service call everything is just fine. How can I be able access the data which is inside of the service call.
Version 1:
Here console log simply states undefined.
.controller('SelectCtrl', ['$scope','$stateParams', '$location', '$window','playerService','tournamentService', function ($scope, $stateParams, $location, $window, playerService, tournamentService) {
init();
function init() {
playerService.getPlayers().then(function (data) {
$scope.players = [];
angular.forEach(data, function (player, index) {
$scope.players.push(player.info);
});
});
tournamentService.getTournaments().then(function (data) {
var result = data.filter(function (element) {
if (element.ID == $stateParams.id) {
return true;
} else {
return false;
}
});
$scope.tournament = result;
});
};
console.log($scope.tournament);//undefined
console.log($scope.players); //undefined
}
Version 2:,
Here console log simply states the Object {then: function, catch: function, finally: function} Which is not what I wan´t I want the data to be able to display it in my view.
.controller('SelectCtrl', ['$scope','$stateParams', '$location', '$window','playerService','tournamentService', function ($scope, $stateParams, $location, $window, playerService, tournamentService) {
init();
function init() {
$scope.players = playerService.getPlayers().then(function (data) {
$scope.players = [];
angular.forEach(data, function (player, index) {
$scope.players.push(player.info);
});
});
$scope.tournament = tournamentService.getTournaments().then(function (data) {
var result = data.filter(function (element) {
if (element.ID == $stateParams.id) {
return true;
} else {
return false;
}
});
$scope.tournament = result;
});
};
console.log($scope.tournament);//Object {then: function, catch: function, finally: function}
console.log($scope.players);//Object {then: function, catch: function, finally: function}
}
Your help is really appreciated!
The Services:
.factory('playerService', function ($http,$q) {
return {
getPlayers: function () {
//return the promise directly.
var deferred = $q.defer();
$http.get(webServiceUrl + 'api/Player/GetAllPlayers')
.success(function (data) {
//resolve the promise as the data
deferred.resolve(data);
}).error(function () {
deferred.reject();
});
return deferred.promise;
}
}
})
.factory('tournamentService', function ($http,$q) {
return {
getTournaments: function () {
//return the promise directly.
var deferred = $q.defer();
$http.get(webServiceUrl + 'api/Tournament/GetAllTournaments')
.success(function (data) {
//resolve the promise as the data
deferred.resolve(data);
}).error(function () {
deferred.reject();
});
return deferred.promise;
}
}
})
Part of the view:
<h1 style="display: inline-block; margin-left:15px;">Enter <i>{{tournament.Name}}</i></h1>
<div class="row">
<div class="selectinforow">
<div class="col-xs-2 selectinfo">
<span>{{tournament.EntryFee}}$</span></br>
<span>Entry Fee</span>
</div>
<div class="col-xs-2 selectinfo">
<span>{{tournament.Entries}}</span></br>
<span>Entries</span>
</div>
<div class="col-xs-2 selectinfo">
<span>{{tournament.Size}}</span></br>
<span>Max Size</span>
</div>
<div class="col-xs-2 selectinfo">
<span>{{tournament.StartTime}}</span></br>
<span>Start Date</span>
</div>
<div class="col-xs-2 selectinfo">
<span>{{tournament.Entryfee*tournament.Entries}}$</span></br>
<span>Winnings</span>
</div>
</div>
</div>
So if you read your code carefully you will notice you are using a promise on the following line:
tournamentService.getTournaments().then(function (data) {
// [your data is set here - AFTER the service call runs]
}
// [your print is here - run BEFORE service call runs]
The key to the "then" statement is it isn't executed right away, but is instead run when data is returned from the service call. In other words, you have your print in the wrong spot - I would expect the values to be undefined there. If you move the console.log statements into the promise (then) - I would expect to see the valid values. You can also put a break point in the browser debugger to see the values in the "then" function if you want to validate that things are working. Hope this puts you on the right track!
EDIT
Once the promise completes, angular automatically updates the view. Lets say you have the following in your view (just an example):
<h1 ng-bind="tournament.Title">Default Text</h1>
When the view/page loads you will see "Default Text". After the promise completes, if a tournament has been loaded, angular will automatically update the "h1" to now have the Title for that tournament. This happens because angular automatically runs an "$apply()" after a promise completes.
Your code is executed before the promise response.
If you need to code "procedurally", you should $watch the scope variable as below to detect any changes.
For example:
$scope.$watch('tournament', function() {
console.log($scope.tournament);
}, true);

Categories

Resources