ProfK
ProfK

Reputation: 51084

Angular module and controller files don't seem to run

I have the following Angular declarations, and get no complaints about JS syntax errors or anything like that:

App.js:

(function () {
    'use strict';

    var hookPointApp = angular.module("hookPointApp", []);
    hookPointApp.controller("agentCtrl", function ($scope, $http) {
        $scope.model = {};
        ...
    });
})();

suburbsCtrl:

(function () {
    'use strict';

    angular.module("hookPointApp").controller('suburbsCtrl', function ($scope, $http) {
        $scope.areas.url = "/Area/ProvinceAreas";
        $scope.areas.getOptions = function (provinceId) {
            var area = "{'provinceId': '" + provinceId + "'}";
            $.ajax({
                url: $scope.areas.url,
                type: "POST",
                data: area,
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                async: false,
                cache: false,
                success: function (response) {
                    if ((response !== null) && (typeof response !== "undefined")) {
                        $scope.areas.options = response;
                    }
                },
                error: function (xmlHttp, textStatus, errorThrown) {
                    alert(errorThrown);
                }
            });
        };
        // TODO Get a proper provinceId somehow.
        $scope.areas.getOptions(1);
        ...
    });
})();

Then I have a repeater with options declared like:

<div ng-controller="suburbsCtrl">
    <div class="form-group">
        @Html.LabelFor(model => model.AreaId, new { @class = "control-label" })
        <select class="form-control" ng-model="areas.areaId" ng-change='areas.getOptions($("#province.val()"))'>
            <option> - Select an Area - </option>
            <option id="province" ng-repeat="item in areas.options" ng-value="{{item.Id}}">{{item.Label}}</option>
        </select>
    </div>
</div>

Yet getOptions isn't called when I change the select option, and breakpoints I put in the Chrome debugger, even on lines not in functions, execution doesn't stop there, e.g. $scope.areas.getOptions(1); which is for initializing a dropdown, is not in a function, but below the function declaration, so I want to declare the function then call it immediately afterwards. A breakpoint in the module file, on var hookPointApp = angular.module("hookPointApp", []); doesn't even work, yet some Angular functionality in the app still sometimes works.

The Angular (core and my own) files are, I think, correctly referenced at the bottom of the body element in Layout.cshtml:

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    <script src="~/Scripts/angular/angular.js"></script>
    <script src="~/Scripts/angular/angular-resource.min.js"></script>
    <script src="~/Scripts/App/App.js"></script>
    <script src="~/Scripts/App/suburbsCtrl.js"></script>
    @RenderSection("ViewScripts", required: false)
</body>

What could I be doing wrong?

Upvotes: 0

Views: 100

Answers (3)

Evans Dianga
Evans Dianga

Reputation: 210

First, Instead of referencing your module through a variable, could you use the getter syntax for the module. I would also split module declaration and c controller definition into separate file. This is in line with John Papa's Angular Style Guide endorsed by the Angular team:

App.js

(function () {
'use strict';

angular.module("hookPointApp", []);    
})();

agentCtrl.js

(function () {
'use strict';


angular.module("hookPointApp").controller("agentCtrl", function ($scope, $http) {
    $scope.model = {};
   });
})();

Secondly, you should probably use $http service of Angular or another library for $http requests e.g Restangular. The issue you have is because you are probably using jQuery's ajax method which upon completion has no way of letting the angular digest loop of knowing that there is a response from the server unless you notify it through $scope.apply().

Note that in the Promise resolution we use the thenmethod of the promise and not success which has been deprecated. Read more here about $http and the deprecation notice.

Here is suburbsCtrl.js with the $http service.

(function () {
'use strict';

angular.module("hookPointApp").controller('suburbsCtrl', function ($scope, $http) {
    $scope.areas.url = "/Area/ProvinceAreas";
  $scope.areas.url = "/Area/ProvinceAreas";
$scope.areas.getOptions = function (provinceId) {
    $http.post($scope.areas.url, {
        provinceId: provinceId
    }).then(function(data){
        if (data) {
            $scope.areas.options = data;
        }
    }).catch(function(err){
      console.error(err);
    });
};
    // TODO Get a proper provinceId somehow.
    $scope.areas.getOptions(1);

});
})();

PS- The Angular documentation encourages using Angular's services and only using jQuery's methods when not available. I would recommend trying to use Angular without external jQuery dependency and use the inbuilt jqLite in Angular for those methods that you would use jQuery for.

Also look at these resources:

https://docs.angularjs.org/guide

"Thinking in AngularJS" if I have a jQuery background?

Upvotes: 2

Huey Zhang
Huey Zhang

Reputation: 131

  • angular.module("hookPointApp", []) (add bracket)
  • use angular http replace jquery ajax, because some time unable update dom.

Try it:

(function () {
'use strict';

angular.module("hookPointApp", []).controller('suburbsCtrl', function ($scope, $http) {
    $scope.areas.url = "/Area/ProvinceAreas";
    $scope.areas.getOptions = function (provinceId) {
        $http.post($scope.areas.url, {
            provinceId: provinceId
        }).success(function(data){
            if (data) {
                $scope.areas.options = data;
            }
        });
    };
    // TODO Get a proper provinceId somehow.
    $scope.areas.getOptions(1);
    ...
});
})();

Upvotes: 0

Huey Zhang
Huey Zhang

Reputation: 131

getOptions() is undefined.

define:

(function () {
    'use strict';

    angular.module("hookPointApp").controller('suburbsCtrl', function ($scope, $http) {
    ...
    // TODO Get a proper provinceId somehow.
    $scope.areas.getOptions(1);
    ...
    $scope.getOptions = function() {
        // on change select , call this
    };
});
})();

Upvotes: 0

Related Questions