Sunday, October 15, 2017

Thoughts on AngularMix 2017

I've been very busy with side projects lately, so it's been a long time since I've taken time to write anything up.

However, I just got back from AngularMix this past week, which was a great experience and was definitely worth a post.  A lot of interesting things are coming out of the Angular world, and I'll share my thoughts on a couple of the highlights (for me).  There were a lot of great talks, but I think my favorite part was the opportunity to meet and talk developers, including some of the core Angular team members.


Angular Elements


One thing that hasn't been as easy in Angular as in AngularJS is just being able to add an Angular component to an existing page.  There's a lot of use cases here, such as having a mix of technologies (React and Angular), or just wanting to start converting functionality from existing server side rendered pages by adding an Angular component.

Rob Wormald gave a talk here on a new enhancements to Angular they are calling "Elements", and had some really nice demos of the early pre-release functionality.  Elements basically allows any component (or even entire application) to run as a standalone custom html that can self-bootstrap into any html page.  He showed an example where was easily able to add independent copies of an Angular component to a static html page, and manipulate it by setting properties on the component.  This is really a HUGE step forward for inter-operability of Angular components with other technologies.

Nx from Nrwl.IO


Nrwl was one of the main sponsors of Angular Mix, and Victor Savkin gave a couple talks here.  One interesting talk was regarding applying a common set of terminologies and message-based design principles in NGRX.  Some of the content is from a post he previously wrote here, which is definitely worth a read.

However, the bigger story for me was the release of Nx, a suite of tools integrated with the CLI for enhancing Angular applications.  There are tools for simplifying generating NGRX code, and also a set of functionlity for supporting breaking up your Angular applications into libraries.  As long as you use a monorepo for your Angular code-base, the Nx tools make it easy to refactor your code into reusable modules.  Until now, it's really not been easy to work with code as libraries in context of CLI-based workflow, so this is a huge step forward.

Developers inherit the Internet


One thing that really amazes me is how web technologies are driven forward by really small groups (or even individuals) who have a passion for improving things, and making lives better for developers.  People make a big deal out of Javascript framework fatigue, but to me this is a symptom of a healthy, thriving community, and seeing the speakers at Angular Mix really drove home the point to me.  With the open source movement, combined with sites like GitHub that  provide ability to share code to anyone in the world for free, pretty much anyone with development skills can make a contribution.  What an amazing time we live in =)

Monday, May 1, 2017

First look at Angular Material 2 Data Table

For anyone working with Angular 2, there's a number of options out there in the data table space, but noticeably lacking has been support for one in the Material 2 project.  If you're looking for good support of material styling, there's only a few options that I've found:

1. MDL - just a styled MDL table, or angularized version.
2. ngx-datatable
3. ng2-md-datatable

These are decent options depending on your needs, but if you've been wanting official version, we've been out of luck till now.  It looks like we finally are getting close to release DataTable in Material 2. Work has been visibly in progress for a while (and people have been begging for it!) over at the official tracking issue here: https://github.com/angular/material2/issues/581

Right now it's still sitting in a fork of the official repo, but I took opportunity to pull the base files out to take a look and get it running in a simple project.

So...for anyone who wants to play with the data table in the context of an Angular CLI based project, I kind of shoehorned the files from the branch into a minimal CLI project, and put the table on the AppComponent page. You can add it to any CLI project by basically following setup done in this base project.

Code is here: https://kmkatsma.github.io/md-table-cli-demo/

Running demo is here: https://kmkatsma.github.io/md-table-cli-demo/

One thing I can't figure out is how to get the headers to show without loading data in the table.  But overall, it seems to be pretty good approach.  I like that it just uses css for sizing and formatting, seems like that's good way to not have to build it into the api of the grid itself.  In any case, excited to finally get a chance to see the work being done!


Saturday, February 25, 2017

Using Docker for Asp.NET Core projects on Windows 10

Recently, I've been trying to get familiar with Docker containers for deployment scenarios, in both Go and .NET Core.  One thing I really wanted was an environment that that supported Docker in both Windows and Linux.  Fortunately, Windows 10 for Docker now supports this.

In order to use Docker for Windows, you must be running Windows 10 Professional.  This is required because Docker for Windows requires Hypervisor, which does not run in Windows 10 Home.

After the Docker for Windows installation, Docker will try to turn Hypervisor on for you, but note that even after upgrading, this might not work.  It did not for me.  Fortunately, I found a great document for resolving Hypervisor problems here at petri.com in case you have issues (one of the rare times StackOverflow didn't immediately answer my problem!).

So after I installed Docker into my windows 10 by following the steps documented at Docker site (they have done great job documenting, I think), I installed the Visual Studio 2017 RC, which has the latest .NET SDK tooling.  I then created a new NET Core Web API using the new project wizard, and checked the option for docker.  For reference, that option is circled below:



By selecting this option, the VS docker tooling automatically adds a Dockerfile and a docker-compose component to the project, which can be used to build and run the project in a docker container.   This is pretty cool, but one thing I don't like is that using the Visual Studio tooling obfuscates what is actually going on under the covers.

In order to get a better feel for what actually is going on in Docker, I switched to using command line to work with docker, and found a decent tutorial here at stormpath.com.  I still had some issues despite following this, and what follows is brief overview of how I got it all working.

First, in my project, I used the following Dockerfile, which I set to "Copy Always" for output option, so the Dockerfile is deployed as part of the "dotnet publish" command.

FROM microsoft/aspnetcore:1.0
COPY . /app
WORKDIR /app
EXPOSE 5000/tcp
ENV ASPNETCORE_ENVIRONMENT Development
ENV ASPNETCORE_URLS http://*:5000
ENTRYPOINT ["dotnet", "Holidays.dll"]

The first line FROM microsoft/aspnetcore:1.0 pulls in an optimized Linux runtime image for aspnetcore project.  The COPY command copies the current directory contents to app folder, and then WORKDIR is set to that /app folder.  I found some comments that using anything besides "/app" will not work, but didn't test.

EXPOSE is used to open up specific port from docker to the outside runtime environment.

The next two ENV lines are used to set runtime environment properties.  These are not required, but I included them as a form of documentation.  If you leave the URL entry out, the container will default to Production environment, and listen on port 80.   The URL entry should match the EXPOSE entry.  By overriding these I just made it clear where values are coming from.

Finally, the ENTRYPOINT starts up the dotnet process running in Kestrel web server, and launches the dll that you pass as second argument.  This should be the name of the dll created during compilation.

After setting up this docker file, then use the following steps at command line, at the root directory of the project you wish build create a container with.  I use Git Bash (some people prefer Powershell).

1. dotnet publish  
2. docker build bin/debug/netcoreapp1.0/publish -t holidays  (note: holidays is what the docker image is named).
3. docker run -d -p 80:5000 --name holidaytest holidays  (note: this creates container, and names is based on value after --name argument.  In this example holidaytest becomes the name of the container created from the image created in step 2, named holidays.  The -p 80:5000 maps the current machines port 80 to the internal port used in the container image set by dockerfile, which was 5000 in my example).

After these steps are complete, you can navigate to the URL for one of the web api controllers on localhost on your machine, and it will run.

To shut down, and then restart this container you can use the following:

docker stop holidaytest
docker start holidaytest

To get a list of images you have on your machine:

docker images

To get a list of containers on your machine, running or not, use:

docker ps -a

It's important to understand the difference between an image, which is just a basic recipe for the container, and the container itself, which is an instantiated version, with port mapping, etc.  I didn't quite get this for a while, and caused me some problems!

Sunday, December 18, 2016

Creating a .NET Core NuGet package with "dotnet nuget" SDK command

I've lately been working some with .NET Core as a host for a new Web API, and have been working with EF Core to handle data access logic.

One thing that I found useful was to create a generic repository abstraction for some core EF behavior, instead of needing to create a repository class for every model class.  I found it was possible to create some generic behavior for Add, Update, Delete, and FindById, and leave anything beyond that to custom search methods.

Instead of having this behavior embedded into the individual projects, I decided to pull the behavior into a NuGet package, which I've called EntityFrameworkCore.GenericRepository, and is available on NuGet now.

For those of your who may not have worked with .NET core class libraries, the existing "dotnet pack" command line method will actually create a NuGet package for a class library automatically.  But it doesn't provide a way to set a lot of the properties that should normally be configured on a package. 

So, to get some of these additional properties, you need to use either NuGet.exe, or you can use some new functionality that's only available in the preview3 (or later) .NET Core SDK.   If you're feeling adventurous, you can download the latest bits and install from a link here:

https://github.com/dotnet/cli

There's a link down the page to SDK installer, which maps here:

https://dotnetcli.blob.core.windows.net/dotnet/Sdk/rel-1.0.0/dotnet-dev-win-x64.latest.exe

After installing this version of SDK, you now can execute following command line:

dotnet nuget pack .nuspec

Run this in the directory of your project where the .nuspec file is located (or pass a path to .nuspec) and this will generate the package for you, and properly use the .nuspec file values.

If you're interested in trying out this generic entity framework behavior, you can find the NuGet package info here:

http://www.nuget.org/packages/EntityFrameworkCore.GenericRepository/

The source code is available, with the .nuspec file I used, is here:

https://github.com/kmkatsma/EntityFrameworkCore.GenericRepository

This currently is using 1.1 version of core, targeting netstandard1.6 (It was necessary to go to 1.1 to support FindById).  If you're using EF Core with 1.1, try it out, and let me know what you think! 

Friday, November 25, 2016

Using Polymer Material Design components with Angular 2

In 2014 Google released a standard design language called Material Design.  It's an impressively detailed specification, with guidelines for pretty much every aspect of modern UI design, down to and including controls.  Depending on the JavaScript framework you're working with, there are different ways to implement Material Design in your application.

In Aurelia, there's a very well developed solution from the angular-ui-toolkits group, the aurelia-materialize-bridge.   I definitely recommend if you're working with Aurelia to check out this library. Most of the Material Design functionality is available and implemented, along with robust styling support. 

If your project is using Angular 2, then the official home for Material Design is at the angular/material2 repo on GitHub.  While there are a number of good building blocks either out there, or in progress, there's also quite a bit missing.  It's currently in alpha, and there's still a lot of work to do.   But if you're wanting to have something more mature, there's an interesting solution using another Google library.

Google Polymer, a Web Component based UI design language, is home to an extensive array of controls in the Material Design format.  The functionality provided by these components is currently significantly more robust than the Angular2 versions.  While these do not natively integrate with Angular2, the folks at Vaadin have implemented a way to get around that.  This is functionality that they're released as an npm package - angular2-polymer.   Rather than me try to explain it myself, I'll use their own words:

The angular2-polymer is a directive factory that aims at bridging the gaps between using Polymer based Web Components in Angular 2 applications.
It scrapes the Polymer element API in order to define Angular 2 outputs and inputs, to apply the ngControl and the ngForm directives, and to observe DOM changes updating the element’s DOM tree appropriately.
 
So I went about following the instructions for integrating Polymer into an Angular2 application.  I have to admit I was soon disappointed with a couple things:
 
  1. Polymer is still using bower for distribution.  There's no npm versions of the polymer controls, and for someone working in Angular2, which has left bower behind, it's feels wrong to go back to having dependencies in bower.
  2. There is no CDN support for Polymer.  I was able to find some "non production ready" CDN's based on the GitHub CDN, and also some old versions of Polymer, but nothing current or official.
But my urge to try the controls was greater than the urge to avoid bower, so I installed it globally, added a bower.json to my project, and proceeded to bring in the various input controls I needed.  At the end, the dependencies in bower looked like this: 


Next, I added a copy step to Webpack to pull in the files to the dist location, and added references to the dist location files to the  index.html.  

The last setup in configuration was to follow the suggestion of a custom "on ready" script checking for web components before loading the angular 2 application:

I then pulled in all the components into a module in Angular2, which is imported into the module housing the Angular 2 components you want to add polymer to:

Finally, I added the polymer controls to my component template, fired up the app, and...it worked.  I had polymer Material Design inputs in my web forms.
 
I was able to hook them up to the model, and get databinding to work without a problem.  For anyone interested in trying out Material Design for Angular2, I definitely recommend you check out the Vaadin angular2-polymer package.  Until all the elements are fully available as native Angular2 components, this is a decent way to get started with Material Design with Angular 2.

Saturday, October 29, 2016

Microsoft's AspNet Javascript Services...now in Aurelia.

In today's complicated web application ecosystem, starting a system from scratch is some seriously hard work.  There's an incredible number of choices to make in terms of frameworks, JS language versions, build processes, back end integration, etc.  And once you choose these things, you have to piece them together.

Fortunately, there's a number of different starter "seed" projects out on GitHub that have some pre-packaged solutions that have most of this work already done.  You can generally find something that is built using the combination of things you're looking for, ready to go.  However, these are almost exclusively *client-side* solutions.  They provide everything you need for front end, but don't have any back end integration. For that you're on your own.  This typically means you're running a development web server with your client, and then have to separately start up a back end - or mock it completely.

But there are a couple end to end solutions out there. For example, ServiceStack has some Visual Studio templates that come in multiple flavors and integrate with ServiceStack APIs.  But I think there's a couple downsides to these.   First, they are using only JSPM.  Webpack is quickly becoming a standard and I would prefer to see them provide at least an option to use Webpack.  Also, more importantly, you need to pay for ServiceStack licenses to use the backend technologies used in the templates.  While ServiceStack is very powerful, it's also not cheap, and so it might not be an option for some teams.

That leaves the other full stack solution I've been able to find - the AspNET JavaScriptServices templates.  These are pretty new, and have a lot of really cool features.  They're using .NET Core, so they are a great opportunity to use latest Microsoft technologies.  They are well integrated with Webpack and take advantage of all its features, like HMR (hot module reloading).  And they all can be launched from single CLI "dotnet run".  The UI and the backend API launch simultaneously, from the same project.  You can have integrated debugging, from front to back and don't need to open up and work with multiple projects.  This is a really nice developer experience.

Until now, the JavaScriptServices templates have only come in Knockout, Angular, and React.  But as of this past Friday, with the merge of a new PR, there is also support for Aurelia.  And, in fact, I was the one who submitted it!  While it's not the most amazing work (and Steve Sanderson at MS deserves credit for the final Webpack configuration), it was work that needed to be done - and was definitely worth doing. 

This was the first time I've made an open source contribution, and it was a great experience.  It's personally rewarding to know that you've made a contribution that others can now use.  I actually wasn't looking for something to contribute to, but while I was reading about the JavaScriptServices templates, I looked through the Issues log and saw there was a request to add support for Aurelia, and that it was up for grabs.  Since I had just gone through some work converting some HTML dashboards to Aurelia and Angular2, and was interested in working with the templates, I figured I might as well try it.  I'm really glad that I did.

As I wrote previously, I think Aurelia is a really well designed framework, and also think that the JavaScriptServices templates provide a great way to develop SPA applications.  Hopefully others who are  interested in using Aurelia can find it useful as a starting point in projects of their own.  There's still work to be done for adding HMR support in Aurelia, so there's opportunity to improve the current implementation.  It looks like this might be available sometime at the end of this year, or start of next.

Finally, I have to comment on how much I like Microsoft's .NET Core environment and tooling.  Their CLI interface gives developers a first class command line experience, which is something quite different from the "Visual Studio does everything approach" we've seen from Microsoft until now.   That approach could result in some strange things, where the build in Visual Studio was very similar, but not quite the same as the MSBuild you'd run as part of an automated process. 

Now, you can easily work with the CLI build, run, and publish commands directly. For developers who are used to working with NPM at the command line for their JavaScript projects, this naturally becomes part of their development process.  I used VS Code (which I also like very much) to do all the editing for both front and back end code, and relied solely on the CLI for doing all the project related tasks.

So, what are you waiting for, go download the JavaScriptServices Aurelia template and try it out!

Sunday, October 16, 2016

Angular 2 and Aurelia, into the app code

In my last post, I discussed my attempts to convert the Gentelella Dashboard into React, Angular2 and Aurelia apps.  There were different levels of success, but in the end I concluded that Aurelia had offered advantages over Angular2 (which was a little more difficult to work with) and React (which was impossible to implement the Dashboard without a re-write).

In this post, I'd like to get into a few more specifics, with examples.  I'll walk through the application structure starting with the bootstrap and ending at the top level component.  While I'm not going into anything complex here, I think it's nice high level view on the differences in structure between the two frameworks.

Bootstrapping

First, when implementing either Aurelia, or Angular2, you need to bootstrap the application into a web page.  In the angular and Aurelia versions, the bootstrapping files are of similar complexity/structure.  Both do some configuration, and then move to the next step in the process.

Angular 2 Bootstrapping

/*
 * Angular bootstraping
 */
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { decorateModuleRef } from './app/environment';
import { bootloader } from '@angularclass/hmr';
/*
 * App Module
 * our top level module that holds all of our components
 */
import { AppModule } from './app';

/*
 * Bootstrap our Angular app with a top level NgModule
 */
export function main(): Promise<any> {
  return platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .then(decorateModuleRef)
    .catch(err => console.error(err));
}

// needed for hmr
// in prod this is replace for document ready
bootloader(main);

The important thing here is pulling in a definition of the AppModule, which contains references to all the components being injected into the main application.

Aurelia Bootstrapping

import {Aurelia} from 'aurelia-framework';
// we want font-awesome to load as soon as possible to show the fa-spinner
import 'font-awesome/css/font-awesome.css';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap';
import '../styles/styles.css';

// comment out if you don't want a Promise polyfill (remove also from webpack.config.js)
import * as Bluebird from 'bluebird';
Bluebird.config({ warnings: false });

export async function configure(aurelia: Aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging();

  // Uncomment the line below to enable animation.
  // aurelia.use.plugin('aurelia-animator-css');
  // if the css animator is enabled, add swap-order="after" to all router-view elements

  // Anyone wanting to use HTMLImports to load views, will need to install the following plugin.
  // aurelia.use.plugin('aurelia-html-import-template-loader')
 

  await aurelia.start();
  aurelia.setRoot('app');

  // if you would like your website to work offline (Service Worker), 
  // install and enable the @easy-webpack/config-offline package in webpack.config.js and uncomment the following code:
  /*
  const offline = await System.import('offline-plugin/runtime');
  offline.install();
  */
}

For Aurelia, the key line above is the setRoot, which invokes the root component for Aurelia. 

At this point they diverge.  The angular App module is a larger construct that knows a lot about the various components that are going to be used in the application.  This is an extra step in the load process between the bootstrap and the eventual top level component.  On the other hand, the Aurelia App just goes straight to the top level component, and its router.

Angular 2 App Module

import { NgModule, ApplicationRef } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';
import { removeNgStyles, createNewHosts, createInputTransfer } from '@angularclass/hmr';

/*
 * Platform and Environment providers/directives/pipes
 */
import { ENV_PROVIDERS } from './environment';
import { ROUTES } from './app.routes';
// App is our top level component
import { App } from './app.component';
import { APP_RESOLVER_PROVIDERS } from './app.resolver';
import { AppState, InteralStateType } from './app.service';
import { Home } from './home';
import { About } from './about';
import { Footer } from './controls/footer.component';
import { Sidebar } from './menu/sidebar.component';
import {FlotCmp} from './controls/network-activities.component'
import { Content } from './content';
import { NoContent } from './no-content';
import { XLarge } from './home/x-large';
import { FontAwesomeDirective } from 'ng2-fontawesome';

// Application wide providers
const APP_PROVIDERS = [
  ...APP_RESOLVER_PROVIDERS,
  AppState
];

type StoreType = {
  state: InteralStateType,
  restoreInputValues: () => void,
  disposeOldHosts: () => void
};

/**
 * `AppModule` is the main entry point into Angular2's bootstraping process
 */
@NgModule({
  bootstrap: [ App ],
  declarations: [
    App,
    About,
    Home,
    Content,
    Footer,
    Sidebar,
    FlotCmp,
    NoContent,
    XLarge,
    FontAwesomeDirective
  ],
  imports: [ // import Angular's modules
    BrowserModule,
    FormsModule,
    HttpModule,
    RouterModule.forRoot(ROUTES, { useHash: true })
  ],
  providers: [ // expose our Services and Providers into Angular's dependency injection
    ENV_PROVIDERS,
    APP_PROVIDERS
  ]
})
export class AppModule {
  constructor(public appRef: ApplicationRef, public appState: AppState) {}

  hmrOnInit(store: StoreType) {
    if (!store || !store.state) return;
    console.log('HMR store', JSON.stringify(store, null, 2));
    // set state
    this.appState._state = store.state;
    // set input values
    if ('restoreInputValues' in store) {
      let restoreInputValues = store.restoreInputValues;
      setTimeout(restoreInputValues);
    }

    this.appRef.tick();
    delete store.state;
    delete store.restoreInputValues;
  }

  hmrOnDestroy(store: StoreType) {
    const cmpLocation = this.appRef.components.map(cmp => cmp.location.nativeElement);
    // save state
    const state = this.appState._state;
    store.state = state;
    // recreate root elements
    store.disposeOldHosts = createNewHosts(cmpLocation);
    // save input values
    store.restoreInputValues  = createInputTransfer();
    // remove styles
    removeNgStyles();
  }

  hmrAfterDestroy(store: StoreType) {
    // display new elements
    store.disposeOldHosts();
    delete store.disposeOldHosts;
  }

}

Some of this is for supporting HMR, but in general this is a big chunk of code.  This module is a central host to the components that are getting loaded into the Angular application.  When you add new controls, you need to come here and add reference to them.  At the top of the file, you can see a number of components are first being imported, and then lower down they are also injected into the module itself.  The next step in the load process is handled via the @NgModule attribute, which has a reference to the bootstrap component, which is loaded first.

In Aurelia, the bootstrapper is where Aurelia is configured, and there's no equivalent central module to this.  The Aurelia bootstrap directly loads the app component which contains the top level router info.  That handles routing for the app template that is loaded up initially.   The difference is that the Angular2 component learns about its components from the App Module, whereas in Aurelia the HTML template does an import of the child components before it can refer to them.  Aurelia moves that composition responsibility to the template side, while it is embedded into the Angular 2 application code.

App Components

The next step in loading the application is starting up the top level App component.  As you can see below the components being used at top level for Angular 2 and Aurelia are actually quite similar.

Angular 2 App Component

/*
 * Angular 2 decorators and services
 */
import { Component, ViewEncapsulation } from '@angular/core';
import 'style!css!less!font-awesome-webpack/font-awesome-styles.loader!font-awesome-webpack/font-awesome.config.js';
import { AppState } from './app.service';

/*
 * App Component
 * Top Level Component
 */
@Component({
  selector: 'app',
  encapsulation: ViewEncapsulation.None,
  styleUrls: [
    './app.style.css'
  ],
  templateUrl: './app.component.html'
})
export class App {

  constructor(
    public appState: AppState) {

  }

  ngOnInit() {
    console.log('Initial App State', this.appState.state);
  }

}

The important thing to notice here is the dependency on the @Component attribute for defining core functionality for the component. The attribute for selector defines how the component can be referenced from html, and the templateURL defines the template that is linked to the component.

Aurelia App Component

import {Aurelia} from 'aurelia-framework';
import {Router, RouterConfiguration} from 'aurelia-router';

export class App {
  router: Router;

  configureRouter(config: RouterConfiguration, router: Router) {
    config.title = 'Aurelia';
    config.map([
      { route: ['', 'dashboard'], name: 'dashboard',      moduleId: './content/dashboard',      nav: true, title: 'Dashboard' },
      { route: 'inbox', name: 'inbox',      moduleId: './content/inbox',      nav: true, title: 'Inbox' },
    ]);

    this.router = router;
  }
}

With Aurelia there is no required attribute necessary to define the selector or the template.  Instead both can be defaulted to be defined by convention.  In this case, as the class name is "App", the template for the html is expected to be app.html, and the html tag will also be "app".  Also, if a css style file was used for just this component it would be defined in  a require from the HTML template, not in the script file.

One thing of note here is that this top level component directly contains the router for the component, whereas in the Angular 2 application the router is in a separate routes component.  There's some differences in how these routers work, but that's a worthy of a completely separate discussion.

HTML Templates

The final files I'd like to compare are the top-level App template files.  With these you can definitely see how Angular2 relies more on the script code files than Aurelia.

Angular 2 App HTML Template

<side-bar></side-bar>
<topnav-bar></topnav-bar>
<router-outlet></router-outlet>
<custom-footer></custom-footer>     

In Angular 2, the top level HTML template is just a list of three custom components and the Angular 2 router outlet.  They are all components that are defined elsewhere. While this is a very minimalistic approach from the template side, what is not obvious is where these custom tags are coming from. You first need to do a search for the selectors to find the component, and then track back from the component to the template if you want to see where are the behavior is coming from.

Aurelia App HTML Template

<template>
  <require from="./menu/topbar"></require>
  <require from="./menu/sidebar"></require>  
  <require from="./controls/custom-footer.html"></require>
  
  <div class="container body">
    <div class="main_container">        
      <sidebar router.bind="router"></sidebar>
      <topbar></topbar>
      <router-view></router-view> 
      <custom-footer></custom-footer>
    </div>
  </div>
     
</template>

There's a bit more template code here in Aurelia.  At the top are the require tags which point directly to the source for the custom tags.  There's also then some extra div tags that are moved here from index.html because of some differences in the way Angular 2 and Aurelia load up, but after that you essentially have same 3 custom components, and the router view for Aurelia.  So the main difference is that the template is more self-descriptive.  With the require tags, there's no mystery where you're pulling these components from.

Finally, one thing I do want to note is the custom-footer reference.  In this case, there was no behavior needed, so it is an HTML only component.  For the Angular 2 version I needed to actually create and import the component script class into the App Module in order to use this custom footer.

Conclusion

Hopefully this write up can be helpful to understand the different design approaches taken by the Angular 2 and Aurelia frameworks.  Aurelia in general has less boilerplate code, and eliminates need for extra steps you need to configure in Angular 2. I found this very powerful for rapid prototyping where I was just piecing together HTML templates to produce a mockup without needing any backing Typescript files.   It was possible to incrementally build up the application, instead of doing more work up front just to things working.

In the end, despite their differences, I do find Aurelia and Angular 2 to be similar enough that it is relatively easy to move between the two.  There's a lot of analogous behavior, and they both are approaching things from the same direction.