kumareloaded
kumareloaded

Reputation: 3952

Calling a function from custom directive on click? - AngularJS

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

Answers (3)

a better oliver
a better oliver

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

cheziHoyzer
cheziHoyzer

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

harishr
harishr

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

Related Questions