Şivā SankĂr
Şivā SankĂr

Reputation: 2036

Explain $apply and $eval | Can I replace them with other function | AngularJS

I have a directive of stripe, Which passing a value a from directive to controller.

Directive

angular.module('stripe', []).directive('stripeForm', ['$window',
function($window) {
  var directive = { restrict: 'A' };
  directive.link = function(scope, element, attributes) {
    var form = angular.element(element);
    form.bind('submit', function() {
      var button = form.find('button');
      button.prop('disabled', true);
      $window.Stripe.createToken(form[0], function() {
        button.prop('disabled', false);
        var args = arguments;
        scope.$apply(function() {
          scope.$eval(attributes.stripeForm).apply(scope, args);
        });
      });
    });
  };
  return directive;

}]);

Controller :

angular.module('myApp', ['stripe'])
.controller('IndexController', function($scope, $http) {
  $scope.saveCustomer = function(status, response) {
    $http.post('/save_customer', { token: response.id });
  };
});

HTML

<form stripe:form="saveCustomer">
  <fieldset>
    <input type="text" size="20" data-stripe="number"/>
    <input type="text" size="4" data-stripe="cvc"/>
    <input type="text" size="2" data-stripe="exp-month"/>
    <input type="text" size="4" data-stripe="exp-year"/>
  </fieldset>
  <button type="submit">Save</button>
</form>

One of my college says using $eval is not a best practice, So I need a alternative to replace scope.$eval.

I also wondering that how the directive is passing value to controller. Pleae explain the code, How it works.

scope.$apply(function() {
   scope.$eval(attributes.stripeForm).apply(scope, args);
});

Ref : https://github.com/gtramontina/stripe-angular

Upvotes: 0

Views: 1018

Answers (1)

amanuel2
amanuel2

Reputation: 4646

Yes the best alternative to $scope.$apply, $scope.$eval, $scope.$digest is $scope.$evalAsync.. In fact its the best practice. So What is, and what is the use of $evalAsync:

$evalAsync

It basically $apply(with more assurance that the code executes first), but it dosent give you the really commonly known error: $apply is already in progress. Same thing with digest: $digest is already in progress.

Code Examples of evalAsync From Fiddle:

Html:

<div ng-app="">
    <div ng-controller="Ctrl">
        <button ng-click="count()">Inc counter</button>
    </div>
    <div ng-controller="EmptyCtrl">
    </div>
</div>

Javascript:

function EmptyCtrl() {

}
function Ctrl($scope) {
    $scope.counter = 0;
    $scope.count = function() {
        $scope.counter ++;
        console.log("setting value to "+$scope.counter)
    };

    var lastValue;
    $scope.$watch(function() {
        var value= $scope.counter;
        if (value!==lastValue) {
            lastValue = value;
            $scope.$evalAsync(function () {
                console.log("value in $evalAsync: "+value)
            });
        }
    });
}

Hope this helped!

Upvotes: 1

Related Questions