May 2017

Volume 32 Number 5

[The Working Programmer]

How To Be MEAN: Angular CRUD

By Ted Neward | May 2017

Ted NewardWelcome back, MEANers.

Last month I explored Angular components—modules, components, services and others—in preparation for a deeper dive into how to create some of those components (msdn.com/magazine/mt795191).

So let’s start applying these component concepts to something more practical.

Command-Line Tooling

Before I get into the component concepts, there’s just one side note I want to make. Some readers e-mailed me to ask if the Git project was the only way to get started with an Angular project; they expressed dubiousness at the idea that this was the only way to get started. As they well suspect, that’s hardly the case. Angular makes available an npm package called angular-cli that can get the barebones structure in place. Using it is straightforward: install, run the generator, answer a few questions and go:

npm install -g @angular/cli
ng new my-app
cd my-app
ng serve

This will create a new application in the my-app subdirectory and ng serve will effectively do an npm start and kick off a long-­running process to run the Web server locally and transpile files as they’re edited.

Whichever approach you use, you’ll end up with a scaffolded “hello world” application; but keep in mind, by the time your project starts to see serious coding, much of that scaffolding will get modified/replaced. So, the actual path you use to get started won’t make much difference in the long run. Use whichever approach feels more comfortable.

Components

When thinking about how to structure a visual application—be it a traditional GUI desktop, a server-based Web application or an SPA application—it helps to think about the application in terms of the identifiable “parts” that can come to mind. Most applications, for example, have a discernible header or footer, usually some kind of menubar or menu structure, and a more generalized content area. Then, within that, there are smaller breakdowns, depending on the goal of the application and the constituent domain entities. One such breakdown is the traditional “master-detail” UI approach in which a user first navigates to a large (usually searchable) overview list of domain entities, selects one and moves into a detailed view of that domain entity. Often, that detailed view can be flipped between read-only and editable states through some kind of button or switch, usually defaulting to a read-only view to start.

The key to all of this is to think in component terms: Where are the convenient boundaries? In the case of an application that wants to display the speakers giving talks and let users of the appli­cation offer their feedback, the components are fairly obvious. (As with most written examples, they’re designed to be.) A few components will be trivial to write—and thus make good first steps—owing to the fact that they involve no user input or editable state, and a few will be a bit more complex, as they’ll likely require both input and reaction to changes in state. The key across all components is a high degree of coherence: The component should basically be a tightly fitting “whole” that represents a “thing,” whatever that “thing” might be.

I’ll start by defining that “thing” as being a simple footer component that will display a copyright message containing the current year.

Now, it’s time to start working on the first component. Assuming you’ve got a cleanly scaffolded project (meaning you’ve thrown away the GreetingsComponent you did last time), you want to build out a new UI component to display a footer at the bottom of the application’s main page. Ideally, this component should display “Copyright (c) (current year), (your company)” across the page, wherever it appears. The assumption is that the users of this component will put it at the bottom of the page, but it’s entirely possible that some odd UI/UX quirk will require something to go below it (perhaps legal disclaimers?), so let’s not make any strong assumptions about where it will appear on the page.

The starting point for a new component is to create it. While there’s always the option of creating files and directories by hand, I like tools that will do the repetitive stuff for me. So I’ll lean on the angular-cli ng tool again, and this time, ask it to generate a component for me:

$ ng generate component footer
installing component
  create src/app/footer/footer.component.css
  create src/app/footer/footer.component.html
  create src/app/footer/footer.component.spec.ts
  create src/app/footer/footer.component.ts
  update src/app/app.module.ts

The generated files aren’t anything magical, and you’ve seen them before: The footer directory contains the FooterComponent scaffolded code, and includes a TypeScript source file, a CSS and HTML file for the UI, and a .spec.ts file specifically for testing this component. It has also updated the application module file (and, sure enough, if you look in that file, it’s been updated to include the footer files and import directive). If the server is still running and you have a browser window open to it, then there will be a brief flicker of “Loading …” and then the application will show up again. (Nothing new is displayed because the UI hasn’t changed, but the flicker is the application being reloaded because of the modifications to the app.module.ts file.) Because it’s easiest to imagine how you’ll want to use this particular component, let’s start with the HTML template in the footer.component.html file. And, in fact, let’s start with how you want to use it.

Fundamentally, I’m thinking that the footer will want to display something along the lines of “Copyright (c) 2017, Neward & Associates, LLC,” which suggests two variabilities in the message displayed: the current year and the copyright owner. One will be generated internally within the component (by creating a new Date object and extracting the year) and one will be passed in from the outside, like so (from app.component.html):

<h1>
  {{title}}
</h1>
<footer owner="Neward &amp; Associates, LLC" />

This suggests that the FooterComponent code needs an input variable (as I discussed in last month’s column) and then also an internal currentYear variable that will be reflected in the HTML (footer.component.html):

<p>Copyright (c) {{currentYear}} {{owner}}</p>

So now, all that remains is to populate the right variables in the FooterComponent itself (footer.component.ts), as shown in Figure 1.

Figure 1 CopyrightComponent

import { Component, Input, OnInit } from '@angular/core';
@Component({
  selector: 'footer',
  templateUrl: './footer.component.html',
  styleUrls: ['./footer.component.css']
})
export class FooterComponent implements OnInit {
  currentYear: string;
  @Input() owner: string;
  constructor() { }
  ngOnInit() {
    var d = new Date();
    this.currentYear = d.getFullYear().toString();
    console.log("Current year is ", this.currentYear);
  }
}

Note that the “selector” value in the @Component decorator defaulted to app-footer and I’ve changed it to footer so as to match the HTML usage I want; this is obviously an aesthetic argument in terms of what the tags should look like. (Some may prefer the app- prefix, but I find it a little redundant.) Whatever your preference, the selector value will define the syntax used in the HTML templates used by other components, so a consistent “style” will go a long way against confusion over time as more and more components are developed, debugged and deployed.

Testing, Testing

Speaking of debugging, one of the things scaffolded out is the .spec.ts file that defines a basic set of unit tests for the component, invoked as part of the test suite that gets executed when running either npm test or ng test. (The test rig is set up to automatically pick up all .spec.ts files under the app subdirectory, so it picks up FooterComponent tests the moment the file is introduced.) Without going into too much detail (yet) about the tests, Figure 2 shows what FooterComponent tests look like.

Figure 2 FooterComponent Test

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import { FooterComponent } from './footer.component';

describe('FooterComponent', () => {
  let component: FooterComponent;
  let fixture: ComponentFixture<FooterComponent>;
  let de: DebugElement;
  let el: HTMLElement;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ FooterComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(FooterComponent);
    component = fixture.componentInstance;
    de = fixture.debugElement.query(By.css('p'));

    component.owner = "ACME, Inc";
    fixture.detectChanges();

    el = de.nativeElement;
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should know the current year', () => {
    const currentYear = "" + new Date().getFullYear();
    expect(component.currentYear).toEqual(currentYear);
  });

  it('should know the owner', () => {
    expect(component.owner).toEqual("ACME, Inc");
  });

  it('should render message in a p tag', async(() => {
    expect(el.textContent).toContain("Copyright (c)");
    expect(el.textContent).toContain(new Date().getFullYear().toString());
    expect(el.textContent).toContain("ACME, Inc");
  }));
});

To those readers who have spent some time writing unit tests in other frameworks, this won’t seem too entirely indecipherable; to wit:

  • describe establishes a unit test suite, which doubles as a scope/context in which all the tests defined therein will run. It provides a place, for example, to hang fields used as part of each test. (Never try to use these across tests; always assume—and ensure—that the fields are reset before and after each test.)
  • beforeEach, as its name implies, is a block of code that runs before each test.
  • it defines a test, consisting of a description and a block of code (which, not surprisingly, is the test in question) to run.
  • expect is a fluent interface, defining a set of expectations that should hold true; if they don’t, the test is considered to have failed.

When run (using either npm test or ng test), a browser window will open and indicate the passing nature—or not—of the code under test. If this process is left to run in the background, by the way, every time a file is changed after the transpiling is done (by the npm server or ng serve process), the tests will automatically run again, giving near-instant feedback on whether the code passes muster.

In this case, the two beforeEach blocks do some standard boilerplate setup, including passing in the owner data that would normally come through the template, and then testing to ensure that the owner data was successfully passed in, that currentYear was correctly calculated, and that the <p> tag in the template, when rendered, will contain the right parts of the copyright message.

And then, of course, the browser window that contains the whole application should also display the new message.

Wrapping Up

At a certain point during every would-be Angular developer’s journey through the opening steps of Angular, there comes a point where the cognitive overhead seems so much higher than the benefits; “After all,” they might muse, “all I really wanted to do was put a copyright message on the bottom of the page!” This is where Angular, like many environments, can be deceiving, in that it might seem to make simple things difficult. Truthfully, that’s not entirely true—you could easily have just dropped the footer on the bottom of the AppComponent in raw HTML and static text, and then you’d have to change it next year, then again when the company gets acquired, and the year after that when the date changes again, and the year after that and so on.

The act of constructing a component is never as freely undertaken as the act of simply “dropping some HTML” onto the page. The pain will come in time, however, as the complexity of the application scales up and developers are forced to remember every page on which the footer appears; by encapsulating the footer into a component, the developer can just use it without having to worry about how the footer comes to decide what message will be displayed. And, just the same, if some later legal scenario requires a more comprehensive message, such as including the license model under which this page is offered to the world, you can change it in one—and only one—place, and that change will silently ripple through the rest of the system without requiring manual intervention.

There’s still much more to explore. In the meantime, happy coding!


Ted Neward is a Seattle-based polytechnology consultant, speaker and mentor, currently working as the director of Developer Relations at Smartsheet.com. He has written more than 100 articles, authored and coauthored a dozen books, and works all over the world. Reach him at ted@tedneward.com or read his blog at blogs.tedneward.com.

Thanks to the following technical expert for reviewing this article: Ward Bell


Discuss this article in the MSDN Magazine forum