Creating the First Screen with Angular Material

Creating the First Screen with Angular Material

Derived from photo by Andy Melton / flickr.com, CC BY-SA

The last post showed how to prototype the Routines App UI using Adobe XD. This post focuses on building the first screen using Angular Material. Before working on the UI, generate a new project using the Angular CLI. If not familiar with the CLI, this is a good resource with which to get started.

This is one of a series of posts detailing the process of building an application with Angular, Visual Studio, ASP.NET Core, and Azure. See the complete list of posts here.

This is a summary of decisions made and lessons learned while creating this screen:

  • Angular Material documentation has everything needed but it took me some time to get the whole mental model, hopefully this post will help anyone else getting started
  • Unlike Bootstrap, Angular Material's CSS doesn't attempt to canvas the whole screen with default CSS and it's more likely you will have to explicitly opt-in than opt-out of the Angular Material theming
  • While the Angular Material setup takes some time, using the components is straightforward by following the examples in the documentation

Adding Angular Material Dependencies

Getting started with Angular Material requires new npm packages, referencing CSS themes, and referencing fonts for Roboto typography and Material icons. First, install the required npm packages for Angular Material:

npm install @angular/cdk && @angular/material

The @angular/material package is somewhat self-explanatory and contains the modules and CSS required to use Angular Material components. The @angular/cdk is interesting. The CDK stands for component developer kit. This is a set of primitive components with defined functionality and API. Using these, anyone can apply custom visual design and extend with custom functionality. Some of the Angular Material themed components are built on top of CDK counterparts. For more information, see the documentation for the CDK data-table.

Next, add references for the Roboto font and Material icons font. These assets are common to the Material design language and Google makes them available on their CDN. Add the following lines in the <head> element of the src/index.html file:

  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">

Angular Material currently includes four pre-built theme options for its components:

  • deeppurple-amber.css
  • indigo-pink.css
  • pink-bluegrey.css
  • purple-green.css

To create a custom theme, Angular Material provides a set of SCSS variables and mix-ins. For now, I'm choosing a pre-built theme. To apply, simply include the link to the pre-built CSS file in the src/styles.css file:

@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';

By referencing the pre-built theme in the styles.css file, the Angular CLI bundles this and other referenced CSS together in one file.

If familiar with CSS frameworks such as Bootstrap, you may be used to the framework applying an extensive set of global styles to the page. Angular Material very deliberately tries to isolate its styles to the Angular Material components. For instance, if you add a regular HTML button to the screen without adding any Angular Material specific markup to it, it renders as the browser would.

Similarly, this also means that CSS used to reset browser-default margins are not applied. The first thing I noticed when starting to add the components to the UI is that I had a default padding around my body element. I found the most straight-forward way to handle this is to apply CSS resets as needed in the styles.css file. At this point, I have only needed to remove the default <body> margin and padding:

/* resets */
body {
  margin: 0;
  padding: 0;
}
/* end resets */

Adding Components

Essentially, this screen has three components: a header, list, and a button. Each of the components in Angular Material is contained within its own NgModule so each of the respective NgModules must be included as an import in the NgModule utilizing the components.

In addition, some of the Angular Material components depend on Angular animations. These are imported using the BrowserAnimationsModule. While I haven't seen any issues using the BrowserAnimationsModule in the component's NgModule versus the application's NgModule (or even removing it altogether), I decided to keep it in the application's NgModule to align with the documentation for now. This is the code for the app.module.ts file:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

For the RoutinesComponent, create a new folder called routines. In this folder are five files:

  • model.ts – type definitions for model objects
  • routines.component.css – the RoutinesComponent CSS
  • routines.component.html – the RoutinesComponent template HTML
  • routines.component.ts – the RoutinesComponent class
  • routines.module.ts – the NgModule to export the RoutinesComponent

Starting with the RoutinesComponent class, there are several things that happen here to create a static UI. First, take a look at the code:

import { Component, OnInit } from '@angular/core';
import { formatDate, areSameDate, addDays } from '../utility';
import { Routine, RoutinesViewModel, RoutineViewModel } from './models';

@Component({
  selector: 'app-routines',
  templateUrl: './routines.component.html',
  styleUrls: ['./routines.component.css']
})
export class RoutinesComponent implements OnInit {
  private routines: Routine[] = [
    {
      name: 'Morning',
      lastCompletedDate: new Date()
    },
    {
      name: 'Social Media',
      lastCompletedDate: new Date(2017, 8, 23, 19, 55)
    },
    {
      name: 'Bedtime',
      lastCompletedDate: new Date(2017, 8, 5, 21, 16)
    }
  ];

  viewModel: RoutinesViewModel = {
    routines: []
  };

  ngOnInit() {
    this.render();
  }

  trackRoutine(routine: RoutineViewModel) {
    return routine.name;
  }

  // TODO: move to own Pipe or Directive
  private mapToDisplayDateText(date: Date): string {
    // TODO: Make today's date mockable, convert to UTC
    const todaysDate = new Date();
    const isToday = areSameDate(todaysDate, date);
    const yesterdaysDate = addDays(new Date(), -1);
    const isYesterday = areSameDate(yesterdaysDate, date);

    const dayText = isToday ? 'Today' : isYesterday ? 'Yesterday' : formatDate(date, 'dddd, MMMM, D, YYYY');
    const lastCompletedDate = `${dayText}, ${formatDate(date, 'h:mm A')}`;

    return lastCompletedDate;
  }

  private render() {
    const viewModel = {
      routines: this.routines.map(routine => {
        const routineViewModel: RoutineViewModel = {
          lastCompletedDate: this.mapToDisplayDateText(routine.lastCompletedDate),
          name: routine.name
        };

        return routineViewModel;
      })
    };

    this.viewModel = viewModel;
  }
}

The component references several models from models.ts. There is a data structure for Routine which I consider more of a domain entity that represents the 'real-world' routine object. Also, there are a several models that represent the data structure of the UI or 'view models'.

The RoutinesComponent has a render method that maps the domain entity to the component's viewModel property. The viewModel property is the main data structure with which to bind the template. To track the items in the list, the class has a trackRoutine function.

The mapToDisplayDateText method should be moved but it's temporary purpose is to create a custom display format for the date. You will also notice some helper functions for Date objects imported from a utility folder.

This component and the required Angular Material NgModules are configured with the RoutinesModule in the routines.module.ts file:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MdToolbarModule, MdListModule, MdButtonModule, MdIconModule } from '@angular/material';

import { RoutinesComponent } from './routines.component';

@NgModule({
  declarations: [
    RoutinesComponent
  ],
  imports: [
    CommonModule,
    MdToolbarModule,
    MdListModule,
    MdIconModule,
    MdButtonModule
  ],
  exports: [
    RoutinesComponent
  ]
})
export class RoutinesModule { }

In addition to the MdToolbarModule (representing the header), MdListModule, and MdButtonModule, there is a re-usable icon module for the button's icon, MdIconModule. Beyond these imports, most of the Angular Material code is in the RoutinesComponent HTML template in routines.component.html file:

<md-toolbar color="primary">
  <span>Routines</span>
</md-toolbar>

<md-nav-list>
  <md-list-item *ngFor="let routine of viewModel.routines; index as i; trackBy: trackRoutine">
    <a>
      <div md-line>
        <span class="mat-title">{{ routine.name }}</span>
      </div>
      <div md-line>
        <span class="mat-subheading-2">{{ routine.lastCompletedDate }}</span>
      </div>
    </a>
  </md-list-item>
</md-nav-list>

<a md-fab class="add-routine-button"><md-icon>add</md-icon></a>

The header is the MdToolbar using the md-toolbar selector. The template uses the color attribute to apply the theme's primary color to the background. For more information on this component, check out the toolbar documentation.

The routine list is made up of the MdList and MdListItem components. A simple ngFor creates each list item. Within each list item, Angular Material's typography CSS classes mat-title and mat-subheading-2 apply the theme's font sizes. Read more about the MdList and MdListItem in the corresponding documentation.

Finally, the button in this case is an MdAnchor component with the md-fab attribute. There are several styles of buttons with their own selectors. To apply the icon, there is an MdIcon component. The MdIcon component's image is configured in the element's content, in this case add. These icons correspond to the list of Material Icons referenced from Google's CDN in the index.html file.

The button is the only component in this screen that has custom CSS to position it fixed in the bottom right of the screen. The CSS for this is in the routines.component.css file.

Read more about the button components here and the icon component here.

One final note is to include the RoutinesModule in the AppModule and the AppComponent template. To see how this fits together, look at the first-angular-material-screen branch in the GitHub repository.

End of the First Round

This being my first time using Angular Material, I found some snags. Hopefully this post helps you avoid the same. Overall, I like my experience with the library so far and I look forward to implementing more advanced scenarios as this application progresses. Have you given Angular Material a try? What do you think? Leave your thoughts in the comments.

Prototyping with Adobe XD and Angular Material

Prototyping with Adobe XD and Angular Material

This is one of a series of posts detailing the process of building an application with Angular, Visual Studio, ASP.NET Core, and Azure. See the complete list of posts here.

This is a summary of decisions made and lessons learned while creating this prototype:

  • Adobe XD is free during the beta period and provides both wireframing and prototyping capabilities
  • Adobe XD comes with a set of Material Design Assets with which to build prototypes
  • Prototyping helps developers understand design considerations before potentially coding themselves into a corner
  • The Material Design assets provided by Adobe XD must be modified in some cases to match what Angular Material provides
  • Prototyping is a great way to start understanding Material Design for those who have never used it

Why Adobe XD?

When designing an application from scratch, it's tempting for developers to dive right into code. However, this often leads to dead ends and rework. Going through the process of wireframing and prototyping helps to understand design problems before investing in their development.

Wireframing is laying out the screens and UI elements. Prototyping is organizing the transitions or flows between these screens and states. Drawing on paper is a low-barrier method to wireframe and prototype. I have done this but I tend to miss the ability to copy and paste repeated UI. There are many software tools that do only wireframing OR prototyping but a much smaller selection accomplish both tasks. One of these applications is Adobe's relatively new Experience Design (XD) product.

There are several reasons I chose to use Adobe XD for this exercise. First, it's made by Adobe which is synonymous with 'professional design tools' and I can assume there is a large base of users from which to find examples, training, and support. Second, Adobe XD is currently free during the beta period. Adobe's Creative Cloud, while exceedingly capable, is arguably expensive at around $50 per month with an annual commitment. Not doing a lot of design work, it becomes difficult to justify this expense. When it's free, however, why not try it? Finally, Adobe XD comes out of the box with Material Design elements (and others) that I leveraged to make my prototype.

To get started, Adobe XD has a built-in tutorial. This was enough to orient me to the major features. However, you can read more about Adobe XD here.

Why Angular Material?

Why choose Angular Material? To start, I wanted to use an existing design language. My main skill is development and so I wanted to leverage existing design work to get my application off the ground as quickly as possible. Material design is a design language based off a set of patterns and principles. Frameworks have adapted these patterns to existing technologies. Angular Material, for instance, has adapted Material Design for Angular.

Angular Material is a set of Angular components built to fit the Material Design language. In addition, Angular Material represents some of the best thinking on how to implement UI component libraries for Angular-based applications. By using this library, I expect to better understand best practices for creating my own re-usable UI components.

Finally, I think Material Design looks good. I find applications built with Material Design to be useable and feel playful. However, I don't know much about it. I don't use many Google applications regularly. By creating a prototype, I can research how these UI components are combined to create an application.

Take the playful aesthetics and combine this with pre-built components, design principles, and prototyping support, and the choice to use Angular Material and Adobe XD makes sense.

Wireframing

Adobe XD offers sets of Material Design, iOS, and Windows assets called UI Kits. When selecting a UI Kit from the menu, Adobe XD opens a new window with a project containing all the assets. From there, you can copy and paste the assets you want to use in your own project.

To start, I copied a view of the Safari browser from the iOS UI Kit. This helps ground the fact that this application will be running in a browser. Next, I opened the Material UI Kit. These assets are designed to mimic native Android apps. To adapt the assets to Angular Material, I opened the Angular Material web site side-by-side with the Angular Material UI KIt. I adapted the existing assets to match what was available in Angular Material. For instance, I combined a text input and menu to recreate the Angular Material select component.

This is what the Material UI Kit gives you out of the box:

Adobe XD Material UI Kit Input

Adobe XD Material UI Kit Menu

This is my own composite to roughly match the Angular Material select:

Angular Material select component

The first screen, referred to as an artboard, takes the most time to create. From there, you can duplicate screens and modify them to wireframe the rest of the application more quickly.

Duplicate artboards worfklow

I didn't spend a lot of time on the initial design, enough to get acquainted with the tool and create the first set of interactions. You can see the current state of the prototype here. Also, visit the Adobe XD documentation to learn more about the program's features.

This is the full set of initial artboards.

Initial application artboards

Prototyping

After the artboards are created, Adobe XD makes it easy to prototype interactions by linking artboards together with transitions.

Adobe XD transitions

Simply select the element that triggers the transition and link it to the target artboard representing the new state.

Adobe XD link transitions

Once all the artboards are linked, you can 'play' the prototype. When in this mode, the artboards are not editable. The user clicks the onscreen elements and Adobe XD displays the linked artboard with the selected transition. This allows the user to get a feel for how the application behaves.

Adobe XD Transition Animation

I almost skipped creating a prototype because I already had an idea of how the screens would flow together. However, the process to create the prototype took very little time and it was somewhat gratifying to see the prototype 'working' even if in a rudimentary state.

Especially if designing this application for other users than myself, the prototype would allow me to perform usability testing. The testing would provide valuable design feedback to incorporate before investing in development effort.

Takeaways

Not being very familiar with Material Design, I had a chance to research how the Angular Material components fit together in an application. Furthermore, I became better acquainted with the various components that Angular Material offers.

I found Adobe XD to be a very capable tool and will consider using it for other application ideas going forward. It was easy to get started and I could become more efficient using the tool with more experience.

I look forward to seeing how Adobe XD evolves overtime and using it more in the future. Have you given it a try? Leave a comment below sharing your experience.

Creating a Project in Visual Studio Team Services

Starting a Personal Project in Visual Studio Team Services

Derived from photo by Ignacio Palomo Duarte / flickr.com, CC BY

This is one of a series of posts detailing the process of building an application with Angular, Visual Studio, ASP.NET Core, and Azure. See the complete listing of posts here.

This is a summary of decisions made and lessons learned while creating this project in Visual Studio Team Services (VSTS):

  • VSTS is free for teams up to 5 users
  • Started with a backlog to outline ideas for the application
  • Only entered items related to the first milestone which is a minimum prototype to validate the application's usefulness
  • Chose Git source control for my VSTS project because of personal preference and because it will be easier to publish the source code publicly to GitHub while maintaining day-to-day work in VSTS
  • Chose the Scrum process template for the VSTS project because the work item flow is slightly simpler given that I am both the developer and the user
  • Created Feature work items for items that, when complete, demonstrate value to the user
  • Created Backlog Item work items for items that benefit the engineering or design process

Creating the Project in Visual Studio Team Services

First, understand that Visual Studio Team Services (VSTS) is free for teams of up to five developers (and unlimited for work item access). This includes free private source control repositories, agile work management, build credits, and more. Check out all the free stuff here.

In VSTS, I created a new project named Bebop. There are two main decisions to make when starting the project, the type of source control to use and the work item template. I chose Git source control because I have grown to really like the ease at which I can create branches and work with multiple repositories. For instance, even though the source code will primarily live privately in VSTS, I will post it publicly to GitHub and Git makes it easy to distribute in this way.

For the process template, I chose the Scrum template. The work item status flow requires slightly less steps which is preferable given that I am the developer and customer at this point. Also, I prefer the terminology of Backlog Item over User Story for organizing work. As a developer, there are many times where system changes are made for performance or security reasons and I find writing user stories such as "As a 'user', I expect my software to be secure…" unnecessary. There are dozens of different ways to approach this configuration so do what's best for your team and project. Here is more information regarding the various process templates built-in to VSTS.

Creating the Backlog

Upon developing the backlog, I started the list in OneNote and then later moved it to Visual Studio Team Services (VSTS). It doesn't really matter the tool when starting, the initial backlog is simply a list of items that need to get done. I also thought of a couple milestones and only added items related to the first. The first milestone is to deliver the minimum feature set that can prove whether my idea for the app will even work in real-world usage. The initial list of backlog items is specific to this goal.

When brainstorming the items, there were two large categories in mind. The first category relates to which items I need to put in place to deliver the demo application. These are things like source control, deployments, etc. I also included in the list to create a prototype design. Before writing any code, it helps to take the initial bucket of features and mock out the user interface and interaction design to help avoid designing into a corner during coding. For these items, I created a Product Backlog Item work item.

The second category of backlog items were the actual features themselves. For these items, I create a Feature work item. Don't worry if you decide to use the work item types differently later as you can change the type if needed. I like to be granular when breaking down features and functionality on the backlog. While there are no deadlines, per se, estimating and tracking these work items is valuable for developing estimation skills and smaller backlog items help enable better estimations. There are other insights that VSTS will give based off these estimations such as a burndown chart for each sprint.

For now, I focused on getting the work into the system which amounts to nothing more than filling out the title of the work item. It will be an ongoing process to refine the list and further schedule it for implementation. This is what the initial list looks like in VSTS:

Backlog Screenshot

In the next post, I'll look at how I'm going to schedule this work in VSTS and organize it into sprints. The process of creating a backlog in VSTS is simple yet there are subtle decisions to make in organizing the work. What are your preferences for creating a backlog in VSTS?

Introducing Project Bebop

Introducing Project Bebop

Derived from photo by Loren Kerns / flickr.com, CC BY

Today starts a new journey on angularfirst.com. Welcome to Project Bebop.

Going forward, each post will detail successes and challenges using Angular, Visual Studio, ASP.NET Core, and Azure in the context of a real application. Being a side-project, helmed by one developer who is also the primary customer, this won't reflect all the considerations of an enterprise application. However, where possible, I will use enterprise-grade development techniques during development.

The goal is that you will gain insight into the benefits and challenges of adopting new technologies and techniques in Angular, Visual Studio, ASP.NET Core, and Azure. More importantly, you will see how these pieces fit together. This is the area that I find the most interesting and plan to focus on these integrations. Developers can't always start from a blank slate and are forced to adopt technologies in an unconventional and/or incremental way with their existing code base. I will get to cover these tradeoffs with examples that you can see in real-time.

The project itself is a personal take on a To-Do application. I'm surprised that given the amount of To-Do applications on the market, I still end up falling back to tools like OneNote and Excel to organize my life. So, I'm going to build one for my own needs and the goal is that anyone else who finds it interesting will be able to use it too.

To be clear, though, the primary goals are learning and sharing. This is an exercise in product development for the lone developer and I'm looking forward to sharing the journey.

This is the list of blog posts related to the project: