Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS code only runs in the html file, not in an external file

This AngularJS code works while located in the HTML file:

<!DOCTYPE html>
<html lang="en" ng-app="ChgReqApp">
    <head>
        <link rel="shortcut icon" href="IM/Coins.png" />
        <title>TITLE</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
        <!-- Change to min -->
        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
        <script>
            angular.module('ChgReqApp', []);
            angular.module('ChgReqApp').controller('MainController', function ($scope) {
                $scope.ClientInfo = {};
                $scope.ChangeRequests = [];
            });
        </script>
        <script src="JS/MainController.js"></script>
    </head>
    <body ng-cloak ng-controller="MainController">
    </body>
</html>

The MainController.js file looks like this and the alert dialog works as expected:

// MainController.js
$(function () {

    alert("MainControllerFile");

});

Now, when I move the controller code to the MainController.js file, I get an error:

<!DOCTYPE html>
<html lang="en" ng-app="ChgReqApp">
    <head>
        <link rel="shortcut icon" href="IM/Coins.png" />
        <title>TITLE</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js">    </script>
        <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
        <!-- Change to min -->
        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
        <script>
            angular.module('ChgReqApp', []);
        </script>
        <script src="JS/MainController.js"></script>
    </head>
    <body ng-cloak ng-controller="MainController">
    </body>
</html>

//MainController.js
$(function () {

    angular.module('ChgReqApp').controller('MainController', function ($scope) {
        $scope.ClientInfo = {};
        $scope.ChangeRequests = [];
    });

});

The error is:

Error: [ng:areq] Argument 'MainController' is not a function, got undefined
http://errors.angularjs.org/1.4.8/ng/areq?p0=MainController&p1=not%20a%20function%2C%20got%20undefined
    at ...

I have searched for a solution to this problem but all the discussions I have found relate to some other issue not applicable to the above code. The external js file is valid and the scripts are in the correct order. Any help on this is greatly appreciated.

like image 630
Phlamajam Avatar asked Jan 19 '16 14:01

Phlamajam


2 Answers

There is no need for $(function() {}) because Angular has its own "Document Ready business" (just to simplify to the max :P).

The problem is that Angular can't run its "Document Ready Business" because you are putting Angular stuff inside jQuery's "Document Ready" shorthand and that stops the Angular framework from working properly.

You can read more about this in Angular's documentation

Angular initializes automatically upon DOMContentLoaded event or when the angular.js script is evaluated if at that time document.readyState is set to 'complete'. At this point Angular looks for the ng-app directive which designates your application root.

I think you can see how this conflicts with what you are trying to do.

Also as an additional suggestion go like this:

angular.module('ChgReqApp', []).controller('MainController', function($scope) {
    $scope.ClientInfo = {};
    $scope.ChangeRequests = [];
});

or like this (my preference)

var app = angular.module('ChgReqApp', []);
app.controller('MainController', function($scope) {
    $scope.ClientInfo = {};
    $scope.ChangeRequests = [];
});
like image 83
Ricardo Velhote Avatar answered Oct 22 '22 16:10

Ricardo Velhote


(function() {

    angular
        .module("ChgReqApp", [])
        .controller("MainController", MainController);

    MainController.$inject = ["$scope"];

    function MainController($scope) {
        $scope.ClientInfo = {};
        $scope.ChangeRequests = [];
    };

})();

you can read more information here : https://github.com/johnpapa/angular-styleguide

like image 32
rbinsztock Avatar answered Oct 22 '22 17:10

rbinsztock