Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how do i avoid $scope.$apply() in the callback

Tags:

angularjs

Below code works fine. I am just trying to see if there is a better way to write it so that i can avoid $scope.$apply() in my controller.

When user clicks on "Sign Up" button, call goes to Controller and then to the Service along with a Callback method. In the Service, i am calling Parse Cloud Code to create the user and calling Callback after i receive the response.

The problem is that i have to call $scope.$apply() in the callback method in order to apply changes to vm.m.resp property bound to the span.

Is there a way i can run the whole signup process as a single transaction and avoid callback?

OR

Is there a way to avoid calling $scope.$apply()?

This is how my UI looks like:

<ion-view title="Sign Up">
  <ion-content class="has-header">
    <div class="list">
      <label class="item item-input">
        <span class="input-label">Username</span>
        <input type="text" ng-model="vm.m.username">
      </label>
      <label class="item item-input">
        <span class="input-label">Password</span>
        <input type="password" ng-model="vm.m.password">
      </label>
      <label class="item">
        <button class="button button-block button-positive" ng-click="vm.doSignUp()">Sign Up</button>
      </label>
    </div>
    <div class="list">
      <div class="bar bar-header bar-positive">
        <span ng-bind="vm.m.resp"></span>
      </div>
    </div>
  </ion-content>
</ion-view>

This is how my Controller looks like:

(function () {
    'use strict';

    angular.module('app').controller('UserAdminCtrl', ['$stateParams', '$scope', 'userAdminApi', UserAdminCtrl]);

    function UserAdminCtrl($stateParams, $scope, userAdminApi) {
        var vm = this;
        vm.m = {};
        vm.m.username = '';
        vm.m.password = '';
        vm.m.resp = '';

        function doSignUp() {

            userAdminApi.doSignup(vm.m, doSignUpCallback);
            vm.m.resp = 'Signing up. Please wait...';
        }

        function doSignUpCallback(resp) {
            vm.m.resp = resp;
            $scope.$apply()
        }
        vm.doSignUp = doSignUp;
        vm.doSignUpCallback = doSignUpCallback;
    };
})();

This is how my service looks like:

(function () {
    'use strict';

    angular.module('app').factory('userAdminApi', [userAdminApi]);

    function userAdminApi() {

        function doSignup(m,cb) {

            Parse.Cloud.run('createUser', {m}, {
                success: function (result) {
                    cb(result);
                },
                error: function (error) {
                    cb(error.message);
                }
            });
        }

        return {
            doSignup: doSignup
        };
    };
})();
like image 643
Asdfg Avatar asked Nov 20 '25 06:11

Asdfg


1 Answers

You can use a promise to get back into the digest cycle:

(function () {
    'use strict';

    angular.module('app').factory('userAdminApi', ['$q', userAdminApi]);

    function userAdminApi($q) {

        function doSignup(m) {
            var deferred = $q.defer();
            Parse.Cloud.run('createUser', {m}, {
                success: function (result) {
                    deferred.resolve(result);
                },
                error: function (error) {
                    deferred.reject(error);
                }
            });
            return deferred.promise;
        }

        return {
            doSignup: doSignup
        };
    };
})();

This gives you a nice and clean error callback as well.

like image 76
Daniel A. White Avatar answered Nov 21 '25 22:11

Daniel A. White



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!