Chieko
Chieko

Reputation: 31

AngularJS - factory in a controller

I'm new to AngularJS and I'm trying to use a .factory that I created in a Controller. When I leave the Factory out, of the dependency array the code files execute w/o any errors. However, as soon as I add the name of the Factory to the controller dependency array, I recieve an error that the name of the controller cannot be found.
Would someone be able to help me correct my controller syntax so that the controller can use and execute without errors. My module, factory and controller are in separate files and they look like this:

angular.module('app', []); // this 'app' is the name of the module.  it needs to be referenced in the berrcontroller or any other controller or service that used this module

(function () // using IIFE
{
    angular.module('app') // 'app' is the name of the module in the BeerApp.js file.
    .factory('BeerFactory', beerFactory);

    function beerFactory() {
        var _brewer = 'Three Floyds';
        var _beer = 'Alpine King';

        var getBeer = function () {
            return _brewer + ' ' + _beer;
        } // getBeer

        return {
            getBeer: getBeer
        };

    }// beerFactory
})(); // function(){

(function () // using IIFE 
{
    angular.module('app') // 'book' is the name of the module in Book.js file.
    .controller('BeerController', beerController);  // second parameter is the dependency array. since we are using controllerAs syntax,$scope not necessary
        // since using vm, have easy naming for all variables

    function beerController(BeerFactory) {
        var vm = this;
        vm.beer = 'generic beer';
        vm.title = "Controller Using a Service";


        activate();

        function activate() {
            return getBeer;
        } // activate

        function getBeer() {
            return beerFactory.getBeer().then(function (data) {
                vm.beer = data;
                return vm.beer
            });
        }//getBeer function
    }
})();
<!DOCTYPE html>
<html lang="en-US">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- tell ie to assume the highest supported version of its rendering engine. -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- content tells the device what width to use. When left out, content appears small because device assumes desktop version -->
    <!-- initial-scale sets the degree to be scaled up by default. -->
    <!-- how do you prevent pinch zoom. -->


    <title>Learning AngularJS</title>

    <!-- Bootstrap   -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" />
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css" rel="stylesheet" />

  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
  
    <!-- add Normalize to make page look the same on all browsers.   -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.2/normalize.css" rel="stylesheet" />

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <!-- custom styles-->
    <style>
    </style>
</head>
<body>
    <header><h1>Service in a controller</h1></header>
    <div ng-app="app">

        <div ng-controller="BeerController as vm">
            <h1>{{vm.title}}</h1>
            {{vm.beer}} is the beer company and name
        </div>
    </div>

    <footer>
        <p>Chieko's beer app.</p>
    </footer>

    <!-- all of the angular js file resources  -->
    <script src="/Scripts/angular.min.js"></script>
    <script src="BeerApp.js"></script>
    <script src="BeerFactory.js"></script>
    <script src="BeerController.js"></script>

</body>
</html>

Upvotes: 2

Views: 77

Answers (5)

Chieko
Chieko

Reputation: 31

Thanks all for your kind help. Here's the corrected version of the Factory:

(function () // using IIFE
{
    angular.module('app') // 'book' is the name of the module in the Book.js file.
    .factory('BeerFactory', beerFactory);

    function beerFactory() {
        var _brewer = 'Three Floyds';
        var _beer = 'Alpine King';

        var getBeer = function () {
            return _brewer + ' ' + _beer;
        } // getBeer

        return {
            getBeer: getBeer
        };

    }// beerFactory
})();   // function(){

This is the correct version of the controller:

(function () // using IIFE 
{
    angular.module('app') // 'book' is the name of the module in Book.js file.
    .controller('BeerController',  ['BeerFactory', beerController]);  // second parameter is the dependency array. since we are using controllerAs syntax,$scope not necessary
        // since using vm, have easy naming for all variables

    function beerController(BeerFactory) {
        var vm = this;
        vm.beer = '';
        vm.title = "Controller Using a Service";

        activate();

        function activate() {
            return getBeer();
            //vm.beer =  BeerFactory.getBeer();

        } // activate    

        function getBeer(beer) {

            vm.beer =  BeerFactory.getBeer();

            return vm.beer;
        }    
    }  })();

The the corresponding html page:

<!DOCTYPE html>
<html lang="en-US">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- tell ie to assume the highest supported version of its rendering engine. -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- content tells the device what width to use. When left out, content appears small because device assumes desktop version -->
    <!-- initial-scale sets the degree to be scaled up by default. -->
    <!-- how do you prevent pinch zoom. -->
    <title>Learning AngularJS</title>
    <!-- Bootstrap   -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" />
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css" rel="stylesheet" />
    <!-- add Normalize to make page look the same on all browsers.   -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.2/normalize.css" rel="stylesheet" />
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <!-- custom styles-->
    <style>
    </style>
</head>
<body>
    <header><h1>Hour 07</h1></header>
    <div ng-app="app">
        <div ng-controller="BeerController as vm">
            <h1>{{vm.title}}</h1>
            {{vm.beer}} is the beer company and name
        </div>
    </div>
    <footer>
        <p>Chieko's beer app.</p>
    </footer>
    <!-- all of the angular js file resources  -->
    <script src="/Scripts/angular.min.js"></script>
    <script src="BeerApp.js"></script>
    <script src="BeerFactory.js"></script>
    <script src="BeerController.js"></script>
</body>
</html>

There were no changes to the App.js file.

Notice that I am not using the '.then(function(data){}) b/c the application didn't work with that part of the code.

Upvotes: 0

Simon Sch&#252;pbach
Simon Sch&#252;pbach

Reputation: 2683

You make everything write except some small mistakes:

first you have to call your IIFE factore with () at the end.

And then you have to care about upper letters. You must inject your factory or controller the same way as you define them.

And last but not least you have to define your controller like

.controller('BeerController', beerController);

angular.module('app', []); // this 'app' is the name of the module.  it needs to be referenced in the berrcontroller or any other controller or service that used this module

(function () // using IIFE
{
    angular.module('app') // 'app' is the name of the module in the BeerApp.js file.
    .factory('BeerFactory', beerFactory);

    function beerFactory() {
        var _brewer = 'Three Floyds';
        var _beer = 'Alpine King';

        var getBeer = function () {
            return _brewer + ' ' + _beer;
        } // getBeer

        return {
            getBeer: getBeer
        };

    }// beerFactory
})(); // function(){

(function () // using IIFE 
{
    angular.module('app') // 'book' is the name of the module in Book.js file.
    .controller('BeerController', beerController);  // second parameter is the dependency array. since we are using controllerAs syntax,$scope not necessary
        // since using vm, have easy naming for all variables

    function beerController(BeerFactory) {
        var vm = this;
        vm.beer = 'generic beer';
        vm.title = "Controller Using a Service";


        activate();

        function activate() {
            return getBeer;
        } // activate

        function getBeer() {
            return beerFactory.getBeer().then(function (data) {
                vm.beer = data;
                return vm.beer
            });
        }//getBeer function
    }
})();
<!DOCTYPE html>
<html lang="en-US">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- tell ie to assume the highest supported version of its rendering engine. -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- content tells the device what width to use. When left out, content appears small because device assumes desktop version -->
    <!-- initial-scale sets the degree to be scaled up by default. -->
    <!-- how do you prevent pinch zoom. -->


    <title>Learning AngularJS</title>

    <!-- Bootstrap   -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" />
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css" rel="stylesheet" />

  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
  
    <!-- add Normalize to make page look the same on all browsers.   -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.2/normalize.css" rel="stylesheet" />

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <!-- custom styles-->
    <style>
    </style>
</head>
<body>
    <header><h1>Service in a controller</h1></header>
    <div ng-app="app">

        <div ng-controller="BeerController as vm">
            <h1>{{vm.title}}</h1>
            {{vm.beer}} is the beer company and name
        </div>
    </div>

    <footer>
        <p>Chieko's beer app.</p>
    </footer>

    <!-- all of the angular js file resources  -->
    <script src="/Scripts/angular.min.js"></script>
    <script src="BeerApp.js"></script>
    <script src="BeerFactory.js"></script>
    <script src="BeerController.js"></script>

</body>
</html>

Upvotes: 0

Wasiq Muhammad
Wasiq Muhammad

Reputation: 3138

Try this

BeerApp.js

var myApp = angular.module('app', []);

BeerFactory.js

 myApp.factory('BeerFactory', beerFactory);

    function beerFactory() {
        var _brewer = 'Three Floyds';
        var _beer = 'Alpine King';

        var getBeer = function () {
            return _brewer + ' ' + _beer;
        } // getBeer

        return {
            getBeer: getBeer
        };

    }// beerFactory


BeerController.js


myApp.controller('BeerController', ['$scope', 'BeerFactory' function($scope, BeerFactory,) {
        var vm = this;
        vm.beer = 'generic beer';
        vm.title = "Controller Using a Service";

        activate();

        function activate() {
            return getBeer;
        } // activate

        function getBeer() {
            return beerFactory.getBeer().then(function (data) {
                vm.beer = data;
                return vm.beer
            });
        }//getBeer function

}]);

Upvotes: 0

theaccordance
theaccordance

Reputation: 889

The actual controller function needs to be at the end of the array, and dependencies you're passing into the controller should be strings within the array, not objects

.controller('BeerController', ['beerFactory', beerController]);

Upvotes: 1

pietro909
pietro909

Reputation: 1861

When you write:

.controller('BeerController', ['beerController', beerFactory]);

you are actually telling Angular to instantiate a Controller passing it beerController which of course doesn't exist yet.

Try this:

.controller('BeerController', ['beerFactory', beerController]);

Upvotes: 0

Related Questions