Creating our application-level controller

As we build our app, we are going to need a couple of scope objects that would be used across the entire application.

We can define these objects in an AppCtrl controller and map it high up in the DOM tree structure so that they can be easily inherited down to the child scopes. Create the AppCtrl controller function in our controllers.js file and then add the following scope objects:

.controller('AppCtrl', ['$scope', 'categoryService',
        function($scope, categoryService) {
            $scope.categories = categoryService.getCategories();
            $scope.user = {};
            $scope.shoppingBasket = [ ];
        }
]);

As you can see, we are making use of both getCategories and categoryService. So, let’s go ahead and create these in our services.js file as follows:

.factory("categoryService", [function() {
        return {

            getCategories: function() {
                var categories = ['Toys', 'Electronics', 'Books', 'Furniture', 'Collectibles'];
                return categories;
            }
        }

    }
]);

Now, let’s attach the AppCtrl controller to the body element in our index.html file, as shown in the following code:

<body ng-controller='AppCtrl'>

While we are at it, let’s also replace our static navigation menu with the dynamic one:

<ul class="nav navbar-nav">
    <li ng-repeat="category in categories"> <a href="#/{{category}}">{{category}}</a>
    </li>
</ul>

Adding a Facebook login

Now that we know how our application would work, we’ll start making it functional. As we are using Facebook as our identity provider, and also as we plan to have our users log in via Facebook to be able to add their products and make purchases, we will need to integrate Facebook with our app.

There are quite a few Facebook modules available for Angular JS. We will be using the module called angular-facebook, which is available at https://github.com/Ciul/angular-facebook.

If you recollect, we added this as a dependency in our bower.json file, and it is already downloaded along with our other libraries.

Let’s include this library into our index.html file as follows:

  <script src="bower_components/angular-facebook/lib/angular-facebook.js"></script>

The next step is to include it as a dependency in our app.js file:

angular.module('myApp', [
 ……
  'facebook'
])

We also need to define our Facebook app ID as a config parameter; we do this in the same app.js file as follows:

.config(['FacebookProvider',function(FacebookProvider){
    FacebookProvider.init('<facebook app id>');
}])

We will now create our factory service that will contain functions to log in and return the user details of the person who has already logged in. Create the authService factory function within the services.js file as follows:

.factory('authService', ['$q', 'Facebook',
    function($q, Facebook) {
        return {

getUserInfo: function() {
                var d = $q.defer();
                Facebook.api('/me', function(response) {
                    d.resolve(response);
                });
                return d.promise;
            },
        };
    }
]);

While creating our authService function, we inject $q and Facebook as dependencies. The getUserInfo method wraps the FacebookAPI request for the /me endpoint and returns the logged in user’s data object. Notice that we are making use of promise to ensure that we get a response with the data.

Next, we will add functionality to our AppCtrl controller to check if the user is logged in and has authorized our app. Add the highlighted code as follows:

.controller('AppCtrl', ['$scope', 'categoryService', 'Facebook', 'authService',
    function($scope, categoryService, Facebook, authService) {
        $scope.categories = categoryService.getCategories();
        $scope.user = {}
        $scope.shoppingBasket = [ ];
        Facebook.getLoginStatus(function(response) {

            if (response.status === 'connected') {
                authService.getUserInfo().then(function(data) {
                    $scope.user = data;
                });
            } else {
                Facebook.login();
            };

        });

    }
])

We first call the getLoginStatus method and check if the response status is connected, that is, we check whether the user has logged in and authorized the app. If this is true, then we make a request to our getUserInfo factory function and store the response in the user scope object. You can log the response to make sure that the logged-in user’s data is being returned in the response.

Next, we will create a directive to show the welcome message to the user and provide links for logout and also a button to trigger the Facebook login.

Let’s create a directive called facebookCheck in the directives.js file as follows:

.directive('facebookCheck', ['Facebook',
    function(Facebook) {

        return {
            link: function(scope, elements, attrs) {

                scope.login = function() {

                    Facebook.login();
                }; 
                scope.logout = function() {
                    Facebook.logout();
                };
            },

            templateUrl: 'partials/facebook-check.html'
        };
    }
]);

Next, we create our template for this directive. Please create a file called facebook-check.html in the partials folder with the following piece of code:

<div class='greeting'>
<p ng-if="user.name"> Welcome {{user.name}} |<a href="#/add"> Add Products</a> |<a href class="glyphicon glyphicon-off" ng- click="logout()"></a></p>
<button class="btn-small btn-info" ng-if="!user.name" ng- click="login()"> FB Login</button>
</div>

We use ng-if to check if user.name is present. If yes, we display the Welcome message, and if not, we will show the Facebook login button.

The last step is to add the directive to our index.html file. We will add it within the <nav> element as follows:

<nav>
   ……
<div class= "col-md-4 pull-right" facebook-check>
</div>
</nav>

Save your files, and test your Facebook login to ensure that it is working. For the sake of better aesthetics, go ahead and add the following CSS class in your app.css to ensure that your welcome text is lined up and is in white color:

.greeting, .greeting a{
  color:#fff;
  line-height: 30px;
}