Tuesday, May 26, 2015

Featured Directive

I'm trying to learn more about using Bootstrap within a .NET MVC application that uses Angular JS.  I figured I'd start easy on myself and try to just change the default everything to use Angular instead of Razor.  That's going pretty well, but one of the issues I came up against was the sections feature of the Razor syntax.  Basically, creating a section in a layout allows you to implement that section within a view that uses the layout and whatever you implement in that section in the "child" view will render wherever that section is rendered in the layout.  Here's the default layout and a default view:

   1:  <!DOCTYPE html>
   2:  <html lang="en">
   3:      <head>
   4:          <meta charset="utf-8" />
   5:          <title>@ViewBag.Title - My ASP.NET MVC Application</title>
   6:          <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
   7:          <meta name="viewport" content="width=device-width" />
   8:          @Styles.Render("~/Content/css")
   9:          @Scripts.Render("~/bundles/modernizr")
  10:      </head>
  11:      <body>
  12:          <header>
  13:              <div class="content-wrapper">
  14:                  <div class="float-left">
  15:                      <p class="site-title">@Html.ActionLink("your logo here", "Index", "Home")</p>
  16:                  </div>
  17:                  <div class="float-right">
  18:                      <section id="login">
  19:                          @Html.Partial("_LoginPartial")
  20:                      </section>
  21:                      <nav>
  22:                          <ul id="menu">
  23:                              <li>@Html.ActionLink("Home", "Index", "Home")</li>
  24:                              <li>@Html.ActionLink("About", "About", "Home")</li>
  25:                              <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
  26:                          </ul>
  27:                      </nav>
  28:                  </div>
  29:              </div>
  30:          </header>
  31:          <div id="body">
  32:              @RenderSection("featured", required: false)
  33:              <section class="content-wrapper main-content clear-fix">
  34:                  @RenderBody()
  35:              </section>
  36:          </div>
  37:          <footer>
  38:              <div class="content-wrapper">
  39:                  <div class="float-left">
  40:                      <p>&copy; @DateTime.Now.Year - My ASP.NET MVC Application</p>
  41:                  </div>
  42:              </div>
  43:          </footer>
  44:   
  45:          @Scripts.Render("~/bundles/jquery")
  46:          @RenderSection("scripts", required: false)
  47:      </body>
  48:  </html>


   1:  @{
   2:      ViewBag.Title = "Home Page";
   3:  }
   4:  @section featured {
   5:      <section class="featured">
   6:          <div class="content-wrapper">
   7:              <hgroup class="title">
   8:                  <h1>@ViewBag.Title.</h1>
   9:                  <h2>@ViewBag.Message</h2>
  10:              </hgroup>
  11:              <p>
  12:                  To learn more about ASP.NET MVC visit
  13:                  <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
  14:                  The page features <mark>videos, tutorials, and samples</mark> to help you get the most from ASP.NET MVC.
  15:                  If you have any questions about ASP.NET MVC visit
  16:                  <a href="http://forums.asp.net/1146.aspx/1?MVC" title="ASP.NET MVC Forum">our forums</a>.
  17:              </p>
  18:          </div>
  19:      </section>
  20:  }
  21:  <h3>We suggest the following:</h3>
  22:  <ol class="round">
  23:      <li class="one">
  24:          <h5>Getting Started</h5>
  25:          ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that
  26:          enables a clean separation of concerns and that gives you full control over markup
  27:          for enjoyable, agile development. ASP.NET MVC includes many features that enable
  28:          fast, TDD-friendly development for creating sophisticated applications that use
  29:          the latest web standards.
  30:          <a href="http://go.microsoft.com/fwlink/?LinkId=245151">Learn more…</a>
  31:      </li>
  32:   
  33:      <li class="two">
  34:          <h5>Add NuGet packages and jump-start your coding</h5>
  35:          NuGet makes it easy to install and update free libraries and tools.
  36:          <a href="http://go.microsoft.com/fwlink/?LinkId=245153">Learn more…</a>
  37:      </li>
  38:   
  39:      <li class="three">
  40:          <h5>Find Web Hosting</h5>
  41:          You can easily find a web hosting company that offers the right mix of features
  42:          and price for your applications.
  43:          <a href="http://go.microsoft.com/fwlink/?LinkId=245157">Learn more…</a>
  44:      </li>
  45:  </ol>

What's going to happen is that when everything renders, the stuff between lines 4 and 20 in the second part of that code up there is going to render on line 32 of the first part of that code up there.  I wanted to replicate that in Angular so I wrote a directive for it.  There are probably lots of other (and possibly better) ways to do this, but this was my first shot and I didn't want to lose that progress.

The directive:
   1:  learnBootstrap.directive('featuredSection', ['$http', '$compile',
   2:      function ($http, $compile) {
   3:          'use strict';
   4:   
   5:          return {
   6:              restrict: 'E',
   7:              replace: true,
   8:              link: function (scope, el, attr, ctrl) {
   9:                  if (attr.templateurl != null) {
  10:                      $http({
  11:                          url: attr.templateurl,
  12:                          method: "GET",
  13:                          cache: true
  14:                      }).then(function (markup) {
  15:                          var compiledTemplate = angular.element($compile(markup.data)(scope));
  16:                          var placeholder = angular.element(document.querySelector("#body"));
  17:                          placeholder.prepend(compiledTemplate);
  18:                      });
  19:   
  20:                      scope.$on("$destroy", function () {
  21:                          var section = angular.element(document.querySelector(".featured"));
  22:                          section.remove();
  23:                      });
  24:                  }
  25:              }
  26:          };
  27:      }
  28:  ]);

The markup to implement that directive:
   1:  <featured-section templateUrl="/Features/Home/Featured.html"></featured-section>

The template the directive is going to retrieve on line 10:
   1:  <section class="featured">
   2:      <div class="content-wrapper">
   3:          <hgroup class="title">
   4:              <h1>{{Title}}</h1>
   5:              <h2>{{Message}}</h2>
   6:          </hgroup>
   7:          <p>
   8:              To learn more about ASP.NET MVC visit
   9:              <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
  10:              The page features <mark>videos, tutorials, and samples</mark> to help you get the most from ASP.NET MVC.
  11:              If you have any questions about ASP.NET MVC visit
  12:              <a href="http://forums.asp.net/1146.aspx/1?MVC" title="ASP.NET MVC Forum">our forums</a>.
  13:          </p>
  14:      </div>
  15:  </section>

No comments:

Post a Comment