bhylu.com

Advertisements

AngularJS ngInclude

ngInclude loads and compiles a template fragment into a view. Its URL must come from a controlled template policy, because loading content as an AngularJS template is much more powerful than displaying it as plain text.

How it works

The fixture server exposes one fixed notice fragment on the same origin. The controller selects that known URL, and the included content reads a caller-owned message. This demonstrates a trusted fragment workflow. Do not let a visitor supply an arbitrary include URL or assume same-origin content is safe merely because it came from your own host.

Run the code

AngularJS 1.8.3 is a legacy framework whose official support ended in January 2022. These examples teach maintenance, not a recommendation for a new application. They need a separate local browser page; Bhylu has no AngularJS playground.

In an empty folder save the HTML below as includes.html and the server as lab-server.mjs. Make a vendor folder and save the four pinned libraries there, retaining their MIT notices. With Node 22 or later run node lab-server.mjs includes.html, then open http://127.0.0.1:8136/. Stop that lab before running a different lesson. The server supplies fixed read-only HTTP fixtures; no data is saved and it does not connect to SQL. No PHP, Apache or MySQL configuration changes are needed.

Example

includes.html

<!doctype html>
<html lang="en" ng-app="repairLab" ng-strict-di>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>AngularJS ngInclude</title>
    <style>
      :root {
        font:
          18px/1.55 system-ui,
          sans-serif;
        color: #0f3464;
        background: #fff;
        color-scheme: light;
      }
      * {
        box-sizing: border-box;
      }
      body {
        margin: 0;
      }
      main {
        max-width: 50rem;
        margin: auto;
        padding: 1.2rem;
      }
      h1 {
        font-size: 1.65rem;
      }
      label {
        display: block;
        margin: 0.6rem 0;
      }
      input,
      select,
      textarea,
      button {
        font: inherit;
        max-width: 100%;
        padding: 0.35rem;
        margin: 0.2rem;
      }
      button {
        border: 1px solid #034fa0;
        border-radius: 0.25rem;
        background: #034fa0;
        color: white;
      }
      button:disabled {
        opacity: 0.55;
      }
      output,
      [role="status"] {
        display: block;
        min-height: 1.5rem;
      }
      table {
        border-collapse: collapse;
        width: 100%;
      }
      td,
      th {
        padding: 0.4rem;
        border: 1px solid #a5bbd4;
        text-align: left;
      }
      pre {
        white-space: pre-wrap;
        overflow-wrap: anywhere;
      }
      :focus-visible {
        outline: 3px solid #0078d4;
        outline-offset: 3px;
      }
      [ng-cloak] {
        display: none !important;
      }
      .marked {
        font-weight: 700;
      }
      .error {
        color: #a02424;
      }
      :root[data-theme="dark"] {
        color: #d6e7fb;
        background: #061d30;
        color-scheme: dark;
      }
      :root[data-theme="dark"] .error {
        color: #ffb4b4;
      }
    </style>
  </head>
  <body>
    <main ng-controller="DeskController as vm" ng-cloak>
      <h1>Community repair desk</h1>
      <p>AngularJS 1.8.3 · Legacy maintenance lab · Local demonstration</p>
      <section ng-include="vm.noticeUrl"></section>
    </main>
    <script src="/vendor/angular.min.js"></script>
    <script>
      (function () {
        "use strict";
        var app = angular.module("repairLab", []);
        app.controller("DeskController", [
          function () {
            var vm = this;
            vm.noticeUrl = "/notice.html";
            vm.notice = "Collection desk closes at five";
          },
        ]);
      })();
    </script>
  </body>
</html>

Focus on the bindings and controller

This excerpt leaves out the document shell, styles and library files. Use the complete download to run it.


<section ng-include="vm.noticeUrl"></section>
<script>
  (function () {
    "use strict";
    var app = angular.module("repairLab", []);
    app.controller("DeskController", [
      function () {
        var vm = this;
        vm.noticeUrl = "/notice.html";
        vm.notice = "Collection desk closes at five";
      },
    ]);
  })();
</script>

Expected result

Collection desk closes at five

The HTTP fixture returns the controlled fragment and AngularJS compiles its binding in the view. The review checks the final paragraph. If you only need received text or permitted sanitized HTML, do not choose ngInclude just because it makes a string appear on screen.

Advertisements