Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrating the MobileServiceClient with AngularJS

I'm trying to use the WindowsAzure.MobileServiceClient within Angular to do single sign on and CRUD operations. Being an Angular noob, I'm trying to figure out the best way to do this:

  • Instantiate it in the $rootScope in .run and call the functions from there?
  • Create a service or factory and make the instantiation of the MobileServiceClient and all of the function calls in that? Would the currentUser and other information get lost when the service/factory isn't being used?
  • Just spool up MobileServiceClient in the controllers that need it? Seems to me if I do it that way, currentUser info would get lost?

I've tried using some of the above methods but I'm running into some problems:

  • Calling the login method as shown in the Azure docs sometimes works, other times it doesn't show a popup window to the authentication provider like it should. I am logged off of the authentication provider so a popup window should be shown but isn't,
  • No matter what I try to do, the MobileServiceClient currentUser is coming back as null, even when the popup was shown and I correctly entered my credentials.

Any ideas of what I can do to make this work smoothly? Any examples I can follow somewhere? The documentation seems sketchy.

I'm using Yeoman and the angular generator along with Grunt to do my work, if it makes any difference.

like image 796
Rob Avatar asked Jan 13 '23 08:01

Rob


2 Answers

I was able to figure it out. I created a new service to handle all of the mobile services code. Since the methods from the client are async, I'm using callbacks in the methods. I also use the cookie store to save the user's credential object (currentUser) and pull it out again when needed. currentUser seems to lose the user credential object between calls, so I store it in a cookie and push it into the client when it has lost it.

'use strict';

angular.module('{appName}')
.factory('AzureMobileClient', ['$cookieStore', function ($cookieStore) {

  var azureMobileClient = {};
  azureMobileClient.isLoggedIn = false;
  azureMobileClient.azureError = "";
  azureMobileClient.azureMSC = new WindowsAzure.MobileServiceClient('{app URL from Azure}', '{app key from Azure}');

  azureMobileClient.login = function(callback, socialMediaService) {

    azureMobileClient.azureMSC.login(socialMediaService).then(function(user) {
      azureMobileClient.isLoggedIn = user != null;
      $cookieStore.put("azureUser", user);
      callback(azureMobileClient.isLoggedIn);
    }
    , function(error){
      alert(error);

      azureMobileClient.azureError = error;
    });
  };

  azureMobileClient.logout = function() {
    azureMobileClient.getUser();
    azureMobileClient.azureMSC.logout();
    $cookieStore.remove("azureUser");
  };

  azureMobileClient.getStuff = function(callback) {
    azureMobileClient.getUser();

    var stuffTable = azureMobileClient.azureMSC.getTable("stuff");

    stuffTable.read().then(function(items) {
      callback(items);
    });
  };

  azureMobileClient.addStuff = function(scope) {
    azureMobileClient.getUser();
    var stuffTable = azureMobileClient.azureMSC.getTable("stuff");
    stuffTable.insert({ stuffname: scope.stuffname });
  };

  azureMobileClient.getUser = function() {
    if (azureMobileClient.azureMSC.currentUser === null)
    {
      azureMobileClient.azureMSC.currentUser = $cookieStore.get("azureUser");
    }
  };

  return azureMobileClient;
}]);

In the controller that does the login and logout, I do this:

'use strict';

angular.module('{appName}')
.controller('MainCtrl', function ($scope, $window, AzureMobileClient) {

    $scope.authenticate = function (socialService) {

        AzureMobileClient.login(function(isLoggedIn) {
            if (isLoggedIn)
            {
                $window.location.href = "/#/play";
            }
        }, socialService);
    };

    $scope.signOut = function() {       
        AzureMobileClient.logout();
    }
});

The view for the login/logout controller looks like this:

<button ng-click="signOut()">Sign Out</button> 
<div class="span4">
        <img src="images/facebooklogin.png" ng-click="authenticate('Facebook')" />
        <img src="images/twitterlogin.png" ng-click="authenticate('Twitter')" />
        <img src="images/googlelogin.png" ng-click="authenticate('Google')" />
    </div>

And finally in a controller that gets data, I do this:

'use strict';

angular.module('{appName}')
.controller('StuffCtrl', ['$scope', '$window', 'AzureMobileClient', function ($scope, $window, AzureMobileClient) {

    AzureMobileClient.getStuff(function(items) {

        if (items.length == 0)
        {
            $window.location.href = "/#/stuff/new";
        }
        else
        {
            $scope.$apply($scope.items = items);
        }   

    });
}]);
like image 133
Rob Avatar answered Jan 17 '23 05:01

Rob


Just for someone who search ready-to-use solution https://github.com/TerryMooreII/angular-azure-mobile-service

This is angularjs service which implement below methods:

  • Azureservice.query(tableName, parameters, withFilterFn)
  • Azureservice.insert(tableName, obj, withFilterFn)
  • Azureservice.update(tableName, obj, withFilterFn)
  • Azureservice.del(tableName, obj, withFilterFn)
  • Azureservice.getAll(tableName, withFilterFn)
  • Azureservice.getById(tableName, id, withFilterFn)
  • Azureservice.read(tableName, parameters, withFilterFn)
  • Azureservice.login(oauthProvider, token)
  • Azureservice.logout()
  • Azureservice.setCurrentUser(userObj)
  • Azureservice.getCurrentUser()
  • Azureservice.isLoggedIn()
  • Azureservice.invokeApi()

Just add 'azure-mobile-service.module' in your dependency list and configure api keys:

 angular.module('your-module-name').constant('AzureMobileServiceClient', {
    API_URL : 'https://<your-api-url>.azure-mobile.net/',
    API_KEY : '<your-api-key>',
 });

and then:

angular.module.('your-module-name').controller('MainController', function ($scope, Azureservice) {
    $scope.loginAction = function () {
        Azureservice.login('facebook').then(function () {
            console.log('login successful');
        }).catch(function () {
            console.log('login error');   
        }
    }
}
like image 42
Alexander Hramov Avatar answered Jan 17 '23 06:01

Alexander Hramov