Reputation: 3952
I'm calling a function from my custom directive on button click.
This is the code I've in my JSP
<input type="button" value="button" text="{{item.id}}" data-href="divSlide" show-notifications>
This is my custom directive
hello.directive("showNotifications", ["$interval", function($interval, $scope) {
return {
restrict: "A",
link: function(scope, elem, attrs) {
//On click
$(elem).click(function() {
console.log('before');
scope.$parent.getJSON(scope.text);
if ($('tr#' + $(this).data("href")).is(":visible")) {
$('tr#' + $(this).data("href")).remove();
} else {
console.log('after');
$(this).closest('tr').after('<tr id="' + $(this).data("href") + '"><td colspan="5">' + $('#' + $(this).data("href")).html() + '</td></tr>');
}
});
},
scope:{
text: "@text"
}
};
}]);
And this is my function
$scope.getJSON= function(id){
jsonService.getJSONData(id).then(function(data){
$scope.data= [];
$scope.data= data['dataList'];
console.log('insidejson');
}
});
};
When I execute the code the console prints the logs in the below order,
before
after
insidejson
But ideally it should be
before
insidejson
after
Why is it executing the next statement after the function call before the function gets executed?
What am I doing wrong?
Upvotes: 1
Views: 1281
Reputation: 26828
You have to return the promise and use it:
$scope.getJSON= function(id){
return jsonService.getJSONData(id).then(function(data){
$(elem).click(function() {
var $element = $(this);
console.log('before');
scope.$parent.getJSON(, scope.text).then(function() {
if ($('tr#' + $element.data("href")).is(":visible")) {
Note that this
would no longer point to the element within the function. So I assigned it to a variable and already wrap it into a jQuery element. I also suggest that you pass the function to the directive:
<input type="button" show-notifications call="getJson">
And in your directive:
scope:{
text: "@text",
call: "="
},
link: function(scope, elem, attrs) {
//On click
$(elem).click(function() {
console.log('before');
scope.call(scope.text).then(...
Upvotes: 2
Reputation: 5021
jsonService.getJSONData
is async call, so the code continue after this line: scope.$parent.getJSON(, scope.text);
without waiting to $scope.getJSON
answer.
to solve it, you can use $q
service.
just add $q
service and use $scope.getJSON
function like this:
$scope.getJSON= function(id){
var deferred = $q.defer();
jsonService.getJSONData(id).then(function(data){
console.log('insidejson');
deferred.resolve(data);
}
});
return deferred.promise;
};
And:
$(elem).click(function() {
console.log('before');
scope.$parent.getJSON(scope.text).then(function(data){
if ($('tr#' + $(this).data("href")).is(":visible")) {
$('tr#' + $(this).data("href")).remove();
} else {
console.log('after');
$(this).closest('tr').after('<tr id="' + $(this).data("href") + '"><td colspan="5">' + $('#' + $(this).data("href")).html() + '</td></tr>');
}
});
});
Now all the code nested in the then
and it will execute after the function getJSON
will resolve the data with this line deferred.resolve(data);
Upvotes: 1
Reputation: 18055
the function
jsonService.getJSONData(id).then(function(data){
$scope.data= [];
$scope.data= data['dataList'];
console.log('insidejson');
}
});
is an async function. hence it will execute in the end
Upvotes: 1