Angular Js + MVC .NEt

0

I'm starting with the issue of Single Page Applications with MVC from .Net, and it has become difficult to solve the dependencies, I've taken the example of the page link and everything is fine, until I use ui.bootstrap components, the point is that the modules that are related to the commonModule, can not access this dependency Download link of the project SPA MVC + AngularJs

CODE of the main App.js:

var commonModule = angular.module('common', ['ngRoute', 'ngAnimate', 'ngSanitize', 'ui.bootstrap']);
var mainModule = angular.module('main', ['common']);

commonModule.factory('viewModelHelper',
    function ($http, $q, $window, $location) {
        return MyApp.viewModelHelper(
            $http, $q, $window, $location);
    });

commonModule.factory('validator', function () { return valJs.validator(); });

mainModule.controller("indexViewModel", function (
    $scope, $http, $q, $routeParams, $window,
    $location, viewModelHelper) {

    var self = this;

    $scope.topic =
        "Integrating ASP.NET MVC and AngularJS";
    $scope.author = "";
});

(function (myApp) {
    var viewModelHelper = function (
        $http, $q, $window, $location) {

        var self = this;

        self.modelIsValid = true;
        self.modelErrors = [];

        self.resetModelErrors = function () {
            self.modelErrors = [];
            self.modelIsValid = true;
        }

        self.apiGet = function (uri, data, success, failure, always) {
            self.modelIsValid = true;
            $http.get(MyApp.rootPath + uri, data)
                .then(function (result) {
                    success(result);
                    if (always != null)
                        always();
                }, function (result) {
                    if (failure != null) {
                        failure(result);
                    }
                    else {
                        var errorMessage = result.status + ':' + result.statusText;
                        if (result.data != null) {
                            if (result.data.Message != null)
                                errorMessage += ' - ' + result.data.Message;
                            if (result.data.ExceptionMessage != null)
                                errorMessage += ' - ' + result.data.ExceptionMessage;
                        }
                        self.modelErrors = [errorMessage];
                        self.modelIsValid = false;
                    }
                    if (always != null)
                        always();
                });
        }

        self.apiPost = function (uri, data, success, failure, always) {
            self.modelIsValid = true;
            $http.post(MyApp.rootPath + uri, data)
                .then(function (result) {
                    success(result);
                    if (always != null)
                        always();
                }, function (result) {
                    if (failure != null) {
                        failure(result);
                    }
                    else {
                        var errorMessage = result.status + ':' + result.statusText;
                        if (result.data != null) {
                            if (result.data.Message != null)
                                errorMessage += ' - ' + result.data.Message;
                            if (result.data.ExceptionMessage != null)
                                errorMessage += ' - ' + result.data.ExceptionMessage;
                        }
                    }
                    if (always != null)
                        always();
                });
        }

        self.goBack = function () {
            $window.history.back();
        }

        self.navigateTo = function (path, params) {
            if (params == null)
                $location.path(MyApp.rootPath + path);
            else
                $location.path(MyApp.rootPath + path).search(params);
        }

        self.refreshPage = function (path) {
            $window.location.href = MyApp.rootPath + path;
        }

        self.clone = function (obj) {
            return JSON.parse(JSON.stringify(obj))
        }

        self.querystring = function (param) {
            if ($location.search != null)
                return $location.search()[param];
            else
                return null;
        }

        self.resetQueryParams = function () {
            $location.url($location.path());
        }

        return this;
    };
    myApp.viewModelHelper = viewModelHelper;
}(window.MyApp));

CODE of App.js for Custumer:

var customerModule = angular.module('customer', ['common']);

customerModule.config(function ($routeProvider,
                                $locationProvider) {
    $routeProvider.when('/customer', {
        templateUrl: '/App/Customer/Views/CustomerHomeView.html',
        controller: 'customerHomeViewModel'
    });
    $routeProvider.when('/customer/list', {
        templateUrl: '/App/Customer/Views/CustomerListView.html',
        controller: 'customerListViewModel'
    });
    $routeProvider.when('/customer/show/:customerId', {
        templateUrl: '/App/Customer/Views/CustomerView.html',
        controller: 'customerViewModel'
    });
    $routeProvider.otherwise({
        redirectTo: '/customer'
    });
    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });
});

customerModule.factory('customerService',
    function ($http, $location, viewModelHelper) {
        return MyApp.customerService($http,
            $location, viewModelHelper);
    });

(function (myApp) {
    var customerService = function ($http, $location,
        viewModelHelper) {

        var self = this;

        self.customerId = 0;

        return this;
    };
    myApp.customerService = customerService;
}(window.MyApp));

RootViewModel CODE (or controler for customer):

customerModule.controller("rootViewModel", function ($scope,$window,customerService, $http, viewModelHelper) {

    // This is the parent controller/viewmodel for 'customerModule' and its $scope is accesible
    // down controllers set by the routing engine. This controller is bound to the Customer.cshtml in the
    // Home view-folder.

    $scope.viewModelHelper = viewModelHelper;
    $scope.customerService = customerService;

    $scope.flags = { shownFromList: false };

    var initialize = function () {
        $scope.pageHeading = "Customer Section";

    }

    $scope.tabs = [
   { title: 'Dynamic Title 1', content: 'Dynamic content 37' },
   { title: 'Dynamic Title 2', content: 'Dynamic content 2', disabled: true }
    ];

    $scope.alertMe = function () {
        setTimeout(function () {
            $window.alert('You\'ve selected the alert tab!');
        });
    };

    $scope.model = {
        name: 'Tabs'
    };
    
    initialize();
});

Code _Layout.cshtml:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" 
              content="width=device-width, initial-scale=1.0">
        <title>@ViewBag.Title - ASP.NET MVC with Angular JS</title>
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body data-ng-app="main">
        <div class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" 
                            data-toggle="collapse" 
                            data-target=".navbar-collapse">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    @Html.ActionLink("ASP.NET MVC/Angular JS", 
                        "Index", "Home",
                        new { area = "" }, 
                        new { @class = "navbar-brand" })
                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li>@Html.ActionLink("Customers",
                                             "Customer",
                                             "Home")</li>
                        <li>@Html.ActionLink("Products", 
                                             "Product", 
                                             "Home")</li>
                        <li>@Html.ActionLink("Orders",
                                             "Order",
                                             "Home")</li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="container body-content">
            @RenderBody()
            <hr />
            <footer>
                <p>&copy; @DateTime.Now.Year</p>
            </footer>
        </div>

        @Scripts.Render("~/bundles/angular")
        <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.2.0.js"></script>
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/bootstrap")
       
        <script type="text/javascript">
            window.MyApp = {};
            MyApp.rootPath = '@Url.Content("~")';
        </script>
        <script src="~/App/Validator.js"></script>
        <script src="~/App/App.js"></script>        
        @RenderSection("scripts", required: false)
        <script type="text/javascript">
            @RenderSection("jsCode", required: false)
        </script>
    </body>
</html>

and finally this is the code of Customer.cshtml, where initially I thought of showing some tabs with data capture forms. but for some reason I can not use the tabs, the dependency to be loaded in the bootstrap commonModule would be supposed to be available.

@{
    ViewBag.Title = "Customers";
}
@section scripts {
    <script src="~/App/Customer/App.js"></script>
    <script src="~/App/Customer/ViewModels/RootViewModel.js"></script>
    <script src="~/App/Customer/ViewModels/CustomerHomeViewModel.js"></script>
    <script src="~/App/Customer/ViewModels/CustomerListViewModel.js"></script>
    <script src="~/App/Customer/ViewModels/CustomerViewModel.js"></script>
}
@section jsCode {
    angular.bootstrap(document.getElementById("customer"), ['customer']);
}

<div ng-non-bindable>

   <div id="customer" data-ng-controller="rootViewModel">
        <h2>{{ pageHeading }}</h2>
        <div class="row">

            <p>Select a tab by setting active binding to true:</p>
            <uib-tabset active="active">
                <uib-tab index="0" heading="Static title">Static content</uib-tab>
                <uib-tab index="$index + 1" ng-repeat="tab in tabs" heading="{{tab.title}}" disable="tab.disabled">
                    {{tab.content}}
                </uib-tab>
                <uib-tab index="3" select="alertMe()">
                    <uib-tab-heading>
                        <i class="glyphicon glyphicon-bell"></i> Alert!
                    </uib-tab-heading>
                    I've got an HTML heading, and a select callback. Pretty cool!
                </uib-tab>
            </uib-tabset>
            <hr />
           
        <hr />*@
        <div ng-view></div>
        <hr />
        <div>
            <a href="/product" target="_self">Products</a>
            &nbsp;|&nbsp;
            <a href="/order" target="_self">Orders</a>
        </div>


    </div>
</div>


I share the details you requested from the application

This is the code that is generated after the render:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" 
              content="width=device-width, initial-scale=1.0">
        <title>Customers - ASP.NET MVC with Angular JS</title>
        <link href="/Content/bootstrap.css" rel="stylesheet"/>
<link href="/Content/site.css" rel="stylesheet"/>

        <script src="/Scripts/modernizr-2.6.2.js"></script>

    </head>
    <body data-ng-app="main">
        <div class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" 
                            data-toggle="collapse" 
                            data-target=".navbar-collapse">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="/">ASP.NET MVC/Angular JS</a>
                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li><a href="/customer">Customers</a></li>
                        <li><a href="/product">Products</a></li>
                        <li><a href="/order">Orders</a></li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="container body-content">
            



<div ng-non-bindable>

   <div id="customer" data-ng-controller="rootViewModel">
        <h2>{{ pageHeading }}</h2>
        <div class="row">

            <p>Select a tab by setting active binding to true:</p>
            <uib-tabset active="active">
                <uib-tab index="0" heading="Static title">Static content</uib-tab>
                <uib-tab index="$index + 1" ng-repeat="tab in tabs" heading="{{tab.title}}" disable="tab.disabled">
                    {{tab.content}}
                </uib-tab>
                <uib-tab index="3" select="alertMe()">
                    <uib-tab-heading>
                        <i class="glyphicon glyphicon-bell"></i> Alert!
                    </uib-tab-heading>
                    I've got an HTML heading, and a select callback. Pretty cool!
                </uib-tab>
            </uib-tabset>
            <hr />
           
        <hr />
        <div ng-view></div>
        <hr />
        <div>
            <a href="/product" target="_self">Products</a>
            &nbsp;|&nbsp;
            <a href="/order" target="_self">Orders</a>
        </div>


    </div>
</div>

            <hr />
            <footer>
                <p>&copy; 2016</p>
            </footer>
        </div>

        <script src="/Scripts/angular.js"></script>
<script src="/Scripts/angular-route.js"></script>
<script src="/Scripts/angular-animate.min.js"></script>
<script src="/Scripts/angular-sanitize.min.js"></script>

        <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.2.0.js"></script>
        <script src="/Scripts/jquery-1.10.2.js"></script>

        <script src="/Scripts/bootstrap.js"></script>
<script src="/Scripts/respond.js"></script>

       
        <script type="text/javascript">
            window.MyApp = {};
            MyApp.rootPath = '/';
        </script>
        <script src="/App/Validator.js"></script>
        <script src="/App/App.js"></script>        
        
    <script src="/App/Customer/App.js"></script>
    <script src="/App/Customer/ViewModels/RootViewModel.js"></script>
    <script src="/App/Customer/ViewModels/CustomerHomeViewModel.js"></script>
    <script src="/App/Customer/ViewModels/CustomerListViewModel.js"></script>
    <script src="/App/Customer/ViewModels/CustomerViewModel.js"></script>

        <script type="text/javascript">
            
    angular.bootstrap(document.getElementById("customer"), ['customer']);

        </script>
    
<!-- Visual Studio Browser Link -->
<script type="application/json" id="__browserLink_initializationData">
    {"appName":"Internet Explorer","requestId":"16e15e461905451fa6f8c1f43ec3ac18"}
</script>
<script type="text/javascript" src="http://localhost:2362/6ba59f2d6de048a6899194e63827ea13/browserLink" async="async"></script>
<!-- End Browser Link -->

</body>
</html>

the route and destinations are in the image.

I include the Project Download Link MVC Project - AngularJS

These are the details you requested from the application

This is the code that is generated after the render:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" 
              content="width=device-width, initial-scale=1.0">
        <title>Customers - ASP.NET MVC with Angular JS</title>
        <link href="/Content/bootstrap.css" rel="stylesheet"/>
<link href="/Content/site.css" rel="stylesheet"/>

        <script src="/Scripts/modernizr-2.6.2.js"></script>

    </head>
    <body data-ng-app="main">
        <div class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" 
                            data-toggle="collapse" 
                            data-target=".navbar-collapse">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a class="navbar-brand" href="/">ASP.NET MVC/Angular JS</a>
                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li><a href="/customer">Customers</a></li>
                        <li><a href="/product">Products</a></li>
                        <li><a href="/order">Orders</a></li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="container body-content">
            



<div ng-non-bindable>

   <div id="customer" data-ng-controller="rootViewModel">
        <h2>{{ pageHeading }}</h2>
        <div class="row">

            <p>Select a tab by setting active binding to true:</p>
            <uib-tabset active="active">
                <uib-tab index="0" heading="Static title">Static content</uib-tab>
                <uib-tab index="$index + 1" ng-repeat="tab in tabs" heading="{{tab.title}}" disable="tab.disabled">
                    {{tab.content}}
                </uib-tab>
                <uib-tab index="3" select="alertMe()">
                    <uib-tab-heading>
                        <i class="glyphicon glyphicon-bell"></i> Alert!
                    </uib-tab-heading>
                    I've got an HTML heading, and a select callback. Pretty cool!
                </uib-tab>
            </uib-tabset>
            <hr />
           
        <hr />
        <div ng-view></div>
        <hr />
        <div>
            <a href="/product" target="_self">Products</a>
            &nbsp;|&nbsp;
            <a href="/order" target="_self">Orders</a>
        </div>


    </div>
</div>

            <hr />
            <footer>
                <p>&copy; 2016</p>
            </footer>
        </div>

        <script src="/Scripts/angular.js"></script>
<script src="/Scripts/angular-route.js"></script>
<script src="/Scripts/angular-animate.min.js"></script>
<script src="/Scripts/angular-sanitize.min.js"></script>

        <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.2.0.js"></script>
        <script src="/Scripts/jquery-1.10.2.js"></script>

        <script src="/Scripts/bootstrap.js"></script>
<script src="/Scripts/respond.js"></script>

       
        <script type="text/javascript">
            window.MyApp = {};
            MyApp.rootPath = '/';
        </script>
        <script src="/App/Validator.js"></script>
        <script src="/App/App.js"></script>        
        
    <script src="/App/Customer/App.js"></script>
    <script src="/App/Customer/ViewModels/RootViewModel.js"></script>
    <script src="/App/Customer/ViewModels/CustomerHomeViewModel.js"></script>
    <script src="/App/Customer/ViewModels/CustomerListViewModel.js"></script>
    <script src="/App/Customer/ViewModels/CustomerViewModel.js"></script>

        <script type="text/javascript">
            
    angular.bootstrap(document.getElementById("customer"), ['customer']);

        </script>
    
<!-- Visual Studio Browser Link -->
<script type="application/json" id="__browserLink_initializationData">
    {"appName":"Internet Explorer","requestId":"16e15e461905451fa6f8c1f43ec3ac18"}
</script>
<script type="text/javascript" src="http://localhost:2362/6ba59f2d6de048a6899194e63827ea13/browserLink" async="async"></script>
<!-- End Browser Link -->

</body>
</html>
the route and the destinations seem to me to be in the image, but in any case if more information is needed, please tell me.

Thanks for the help!

I include the Project Download Link MVC Project - AngularJS

    
asked by Cesar Perez Ramirez 18.10.2016 в 01:06
source

1 answer

1

Looking at the code you have put it is difficult to know all the details that may go wrong because the application is quite large but this highlights me in view a trick that they use and that they do boostrap twice to the application

The first time it happens when you call

<body data-ng-app="main">

Using the ng-app directive will use main as the main module of your application.

Elsewhere you use the ng-non-bindable directive that makes the angle ignore all the content that is inside that div and does not process it .

<div ng-non-bindable>
    <div id="customer" data-ng-controller="rootViewModel">

Apparently that is to be able to do later

angular.bootstrap(document.getElementById("customer"), ['customer']);

In short you have two (or more) applications of angular running at the same time on your page which will make it very difficult to reason your application when it keeps growing.

My recommendation is that if you want to learn angular do a single main page and load a single main module with the other modules as dependencies (load them all) and use some routing solution like ui-router (recommended) or ngRoute (that you already load it anyway), otherwise you'll keep fighting for trying to solve simple problems using a very complex structure and this can only bring you problems.

If the previous recommendation does not satisfy you, you can solve your current problem by adding 'ui.bootstrap' as a dependency of your module customer (and all the modules that you declare after this one)

var customerModule = angular.module('customer', ['common', 'ui.bootstrap']);

This is one of the consequences of doing bootstrap more than once in the application.

    
answered by 18.10.2016 в 15:20