The tale of mvc, require.js and angular. is there ever

So. There were once four magical creatures: asp.net mvc, require.js and angular. And one wise wizard decided to put them in one house, and let each asp.net look have its own javascript file with the code "behind" code,

he first added to _Layout.cshtml

  <script data-main="/main" src="~/Scripts/require.js"></script> 

and then he created main.js in the root:

 require.config({ baseUrl: "/Scripts/", paths: { 'jquery': 'jquery-1.9.1.min', 'jquery-ui': 'jquery-ui-1.10.2.custom.min', 'angular': 'angular.min', 'ng-grid': 'ng-grid-2.0.2.debug' }, shim: { 'jquery': { exports: "$" }, 'underscore': { exports: "_" }, 'jquery-ui': ['jquery'], }, }); // Standard Libs require(['jquery','jquery-ui','underscore','angular']); 

nothing unusual and magical. But then he created the html helper as such:

 public static MvcHtmlString RequireJs(this HtmlHelper helper) { var controllerName = helper.ViewContext.RouteData.Values["Controller"].ToString(); // get the controllername var viewName = Regex.Match((helper.ViewContext.View as RazorView).ViewPath, @"(?<=" + controllerName + @"\/)(.*)(?=\.cshtml)").Value; //get the ViewName - extract it from ViewPath by running regex - everything between controllerName +slash+.cshtml should be it; // chek if file exists var filename = helper.ViewContext.RequestContext.HttpContext.Request.MapPath("/Scripts/views/" + controllerName.ToLower() + "-" + viewName.ToLower()+".js"); if (File.Exists(filename)) { return helper.RequireJs(@"views/" + controllerName.ToLower() + "-" + viewName.ToLower()); } return new MvcHtmlString(""); } public static MvcHtmlString RequireJs(this HtmlHelper helper, string module) { var require = new StringBuilder(); require.AppendLine(" <script type=\"text/javascript\">"); require.AppendLine(" require(['Scripts/ngcommon'], function() {"); require.AppendLine(" require( [ \"" + module + "\"] );"); require.AppendLine(" });"); require.AppendLine(" </script>"); return new MvcHtmlString(require.ToString()); } 

and then he could use it in _Layout.cshtml exactly the same way:

  @Html.RequireJs() 

and if you listen carefully to this story, you probably noticed that there was a Scripts/ngcommon.js for the Scripts/ngcommon.js manual bootstrap and you usually used angular directives and services

 require(['angular', 'jquery'], function() { angular.module("common",[]).directive('blabla', function() { return { restrict: 'A', scope: { value: "@blabla" }, link: function(scope, element, attrs) { } } }); //manually bootstrap it to html body $(function(){ angular.bootstrap(document.getElementsByTagName('body'), ["common"]); }); }); 

And here comes the magic: now, if it was a javascript file in \ Scripts \ views, named controllerName-viewName.js, like home-index.js for Home \ Index.cshtml, it automatically selected require.js and loaded it. Great, isn't it?

But then the wizard thought: β€œWhat if I need to load something else (for example, ng-grid) and that something should not be entered into the general angular module, because not all pages will use it. Of course, he could always manually loading another module into a page element in every coded javascript where it is needed, but it is not wise enough to find the answer to the question: Is it possible to insert some angular.js component (for example, ng-grid) directly into the controller without it as part of an application module?

+7
source share
2 answers

If I understand the idea of ​​the magician correctly, then you can continue by breaking the application into submodules defined as a set of components.

It will work if it installs dependencies for the main module myApp , for example:

 var myApp = angular.module('myApp', ['Constants', 'Filters', 'Services', 'Directives', 'Controllers']); myApp.Constants = angular.module('Constants', []); myApp.Controllers = angular.module('Controllers', []); myApp.Filters = angular.module('Filters', []); myApp.Services = angular.module('Services', []); myApp.Directives = angular.module('Directives', []); 

Then each of the submodules: Services , etc. - can be expanded using one component, for example:

 myApp.Controllers.controller('MyController', function () {}); myApp.Services.factory('myService', function () {}); myApp.Directives.directive('myDirective', function () {}); myApp.Filters.filter('myFilter', []); myApp.Constants.constant('myConstant', []); 

Thus, the main application module is loaded with several submodules, but each structure is not important. This allows you to include separate controllers, services, directives and filters on each page served using the background interface. You just need to make sure that all the necessary dependencies are loaded.

+1
source

DI is the magic key for marking up angular code in MVC views. You don't even need requirejs at all, because angular is a dependency loader and module loader by nature, angular.bootstrap is a magical place to run.

So, let the wizard become more powerful with the $ inject spell .

  var TmplController = function($scope, $compile, $http... // any module itself { this.parts = ['legs','arms','head']; $scope.dynamicPageTemplate = function($compile) { $compile('<div><p ng-repeat="each in parts">{{each}}</p></div>' )( $scope ); } } TmplController.$inject = ['$scope','$comple', '$http']; //try legs or head 

specify the full annotated source angular -scenario.js from https://github.com/angular/bower-angular-scenario and you will find how to enter the code using the helper detection method.

0
source

All Articles