简体   繁体   中英

AngularJS Module is undefined while creating service using Factory method

I am learning AngularJS in MVC and created service to pass my model to Angular Controller. But It gives me error

JavaScript runtime error: 'accountModule' is undefined

This is what I am doing:

AccountController.cs

public ViewResult Index()
{
    var accounts = new List<Accounts>
                        {
                            new Accounts
                                {
                                    Id = 111,
                                    Designation = "Tech Lead",
                                    Name = "AAA"
                                },
                            new Accounts
                                {
                                    Id = 222,
                                    Designation = "Softwre Engineer",
                                    Name = "BBB"
                                },
                            new Accounts
                                {
                                    Id = 111,
                                    Designation = "Project Manager",
                                    Name = "CCC"
                                }
                        };

    var settings = new JsonSerializerSettings
                        {
                            ContractResolver = new CamelCasePropertyNamesContractResolver()
                        };

    var accountJson = JsonConvert.SerializeObject(accounts, Formatting.None, settings);

    return this.View("Index", (object)accountJson);
}

Index.cshtml

<script type="text/javascript" src="../../Scripts/Modules/Account/Account.js"></script>
<div ng-app="accountModule">
    <div ng-controller="accountController">
        <h1>{{message}}</h1>
        <div class="container" ng-init="employees in {{employees}}">
            <h2>Employee Details</h2>
            <div class="row">
                <table class="table table-condensed table-hover">
                    <tr>
                        <td>
                            ID
                        </td>
                        <td>
                            Name
                        </td>
                        <td>
                            Designation
                        </td>
                    </tr>
                    <tr ng-repeat="emp in employees">
                        <td>
                            {{emp.id}}
                        </td>
                        <td>
                            {{emp.name}}
                        </td>
                        <td>
                            {{emp.designation}}
                        </td>
                    </tr>
                </table>
            </div>
        </div>
        <div>
            @*{{emps}}*@
        </div>
    </div>
</div>

<script type="text/javascript">

    accountModule.factory('accountService', function() {
            var factory = {};

            factory.employees = @Html.Raw(Model);

            return factory;
        });

</script>

Account.js

var account = angular.module('accountModule',[]);

account.controller('accountController', [
    '$scope', 'accountService', function ($scope, accountService) {


        $scope.employees = accountService.employees;

        $scope.message = "Hi on " + (new Date()).toDateString();
    }
]);

I don't understand where I am going wrong.

You need to move the inline script right after the account.js.

Also the variable should be account instead of accountModule

Code

<script src="angular.js"></script>
<script src="app.js"></script>
<script src="account.js"></script>
<script type="text/javascript">
//account.factory('accountService', function() { //this is alternative use below one
angular.module('accountModule').factory('accountService', function() {
    var factory = {};

    factory.employees = @Html.Raw(Model);

    return factory;
});
</script>

MVC View rendering order- 1. Starts with the View first and then related bundles(external CSS,JS).

2.In order to pass the Model data we need to have a inline element in .cshtml file(though not recommended) but, if this is the way to go then, use service injection to related controller-

@section scripts
    {
    <script>
    (function (undefined) {
        window.app.factory('searchBinding', function () {
            return @Html.Raw(Json.Encode(Model))
        })
    })(undefined);

</script>
}
  1. Now, as the above code is inline it gets executed with the View itself, but Angular module is not yet defined as its yet to be downloaded. Hence it will throw the undefined error.

  2. In order to resolve this we can use RenderSection in _Layout.cshtml after all the core files(bundles) are loaded , this forces even the inline sections to load only after these files are loaded(in step-2. @section scripts was used for this purpose).Snippet from _Layout.cshtml file

    @Scripts.Render("~/bundles/angularjs"); @RenderSection("scripts",false);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM