Injector error with angular

432 views Asked by At

I have the following error on my APP

Error: [$injector:unpr] http://errors.angularjs.org/1.3.2/$injector/unpr?p0=ProductResourceProvider%20%3C-%20ProductResource

My Scenario is as follows, a simple app that gets info from a webservice, but with ng mock I want to load the products if the webservice is not implemented.

In my head tag I used the code like this:

<script src="//code.jquery.com/jquery-2.1.1.min.js" type="text/javascript"></script>    
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js" type="text/javascript"></script>
    <script src="//code.angularjs.org/1.3.2/angular-resource.min.js" type="text/javascript"></script>
    <script src="//code.angularjs.org/1.3.2/angular-mocks.js" type="text/javascript"></script>


    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.2.js"c></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>|

    <!-- Application Script -->
    <script src="../Scripts/App/App.js" type="text/javascript"></script>

    <!-- Services -->
    <script src="../Scripts/App/Common/Services/common.services.js"  type="text/javascript"></script>
    <script src="../Scripts/App/Common/Services/productResource.js"></script>
    <script src="../Scripts/App/Common/Services/productResourceMock.js" type="text/javascript"s></script>

    <!--Controllers -->
    <script src="../Scripts/App/Products/ProductListCtrl.js" type="text/javascript"></script>

My App.Js defines the module and its dependencies:

(function () {
    "use strict";
    var app = angular.module("productManagement", ["common.services", "productResourceMock"]);
}());

The Product Controller, very simple:

(function () {
    "use strict";
    angular
        .module("productManagement")
        .controller("ProductListCtrl",
                    ["ProductResource",
                    ProductListCtrl]);

    function ProductListCtrl(productResource) {
        var vm = this;

        productResource.query(function (data) {
            vm.products = data;
        });

        vm.showImage = false;

        vm.toggleImage = function () {
            vm.showImage = !vm.showImage;
        }
    }
}());

The Common.Services (which has ng-resource)

(function () {
    "use strict";

    angular
        .module("common.services",
                ["ngResource"])
}());

Then product resource

   (function () {
        "use strict";

        angular
            .module("common.services")
            .factory("productResource",
                    ["$resource",
                     productResource]);

        function productResource($resource) {
            return $resource("/api/products/:productId")
        }

    }());

and finally product resource mock

(function () {
    "use strict";

    var app = angular
                .module("productResourceMock",
                        ["ngMockE2E"]);

    app.run(function ($httpBackend) {
        var products = [
            {
                "productId": 1,
                "productName": "Leaf Rake",
                "productCode": "GDN-0011",
                "releaseDate": "March 19, 2009",
                "description": "Leaf rake with 48-inch wooden handle.",
                "cost": 9.00,
                "price": 19.95,
                "category": "garden",
                "tags": ["leaf", "tool"],
                "imageUrl": "http://openclipart.org/image/300px/svg_to_png/26215/Anonymous_Leaf_Rake.png"
            },
            {
                "productId": 2,
                "productName": "Garden Cart",
                "productCode": "GDN-0023",
                "releaseDate": "March 18, 2010",
                "description": "15 gallon capacity rolling garden cart",
                "cost": 20.00,
                "price": 32.99,
                "category": "garden",
                "tags": ["barrow", "cart", "wheelbarrow"],
                "imageUrl": "http://openclipart.org/image/300px/svg_to_png/58471/garden_cart.png"
            },
            {
                "productId": 5,
                "productName": "Hammer",
                "productCode": "TBX-0048",
                "releaseDate": "May 21, 2013",
                "description": "Curved claw steel hammer",
                "cost": 1.00,
                "price": 8.99,
                "category": "toolbox",
                "tags": ["tool"],
                "imageUrl": "http://openclipart.org/image/300px/svg_to_png/73/rejon_Hammer.png"
            },
            {
                "productId": 8,
                "productName": "Saw",
                "productCode": "TBX-0022",
                "releaseDate": "May 15, 2009",
                "description": "15-inch steel blade hand saw",
                "cost": 6.95,
                "price": 11.55,
                "category": "garden",
                "tags": ["garden", "mower"],
                "imageUrl": "http://openclipart.org/image/300px/svg_to_png/27070/egore911_saw.png"
            },
            {
                "productId": 10,
                "productName": "Video Game Controller",
                "productCode": "GMG-0042",
                "releaseDate": "October 15, 2002",
                "description": "Standard two-button video game controller",
                "cost": 2.22,
                "price": 35.95,
                "category": "gaming",
                "tags": ["gaming", "controller", "video game"],
                "imageUrl": "http://openclipart.org/image/300px/svg_to_png/120337/xbox-controller_01.png"
            }
        ];

        var productUrl = "/api/products"

        $httpBackend.whenGET(productUrl).respond(products);

        var editingRegex = new RegExp(productUrl + "/[0-9][0-9]*", '');
        $httpBackend.whenGET(editingRegex).respond(function (method, url, data) {
            var product = {"productId": 0};
            var parameters = url.split('/');
            var length = parameters.length;
            var id = parameters[length - 1];

            if (id > 0) {
                for (var i = 0; i < products.length; i++) {
                    if (products[i].productId == id) {
                        product = products[i];
                        break;
                    }
                };
            }
            return [200, product, {}];
        });

        $httpBackend.whenPOST(productUrl).respond(function (method, url, data) {
            var product = angular.fromJson(data);

            if (!product.productId) {
                // new product Id
                product.productId = products[products.length - 1].productId + 1;
                products.push(product);
            }
            else {
                // Updated product
                for (var i = 0; i < products.length; i++) {
                    if (products[i].productId == product.productId) {
                        products[i] = product;
                        break;
                    }
                };
            }
            return [200, product, {}];
        });

        // Pass through any requests for application files
        $httpBackend.whenGET(/app/).passThrough();


    })
}());

I checked the spelling and found nothing yet, so I am sure what I am missing here

and before I forget the rest of the html

 <div ng-app="productManagement" class="container">
        <div class="panel panel-primary">
            <div class="panel-heading"
                 style="font-size:large">Product
            List
            </div>

            <div class="panel-body">
                <table class="table" ng-controller="ProductListCtrl as vm">
                    <thead>
                    <tr>
                        <td>
                            <button type="button"
                                    class="btn btn-primary"
                                    ng-click="vm.toggleImage()">
                                {{vm.showImage ? "Hide" : "Show"}} Image
                            </button>
                        </td>
                        <td>Product</td>
                        <td>Code</td>
                        <td>Available</td>
                        <td>Price</td>
                    </tr>
                    </thead>
                    <tbody>
                    <tr ng-repeat="product in vm.products">
                        <td>
                            <img ng-if="vm.showImage"
                                    ng-src="{{product.imageUrl}}"
                                    style="width:50px;margin:2px"
                                    title="{{product.productName}}">
                        </td>
                        <td>{{ product.productName}}</td>
                        <td>{{ product.productCode }}</td>
                        <td>{{ product.releaseDate }}</td>
                        <td>{{ product.price | currency }}</td>
                    </tr>
                    </tbody>
            </table>
            </div>
        </div>
    </div>
1

There are 1 answers

0
Yngve B-Nilsen On BEST ANSWER

Spelling is off here - the ProductResource-factory is defined as .factory("productResource") with lowercase p:

(function () {
    "use strict";
    angular
        .module("productManagement")
        .controller("ProductListCtrl",
                    ["ProductResource",
                    ProductListCtrl]);

    function ProductListCtrl(productResource) {
        var vm = this;

        productResource.query(function (data) {
            vm.products = data;
        });

        vm.showImage = false;

        vm.toggleImage = function () {
            vm.showImage = !vm.showImage;
        }
    }
}());