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) { } } });
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?