Managing Multiple Bootstrap Modals

Introduction

If you have managed to find your way to this blog, there is no doubt that you also have some experience with bootstrap. We here at Arroyo Labs love the bootstrap as it provides us the tools to enhance the user experience of our products. Although we love its shiny new toy aspects of bootstrap,they always come with some unexpected complexity.

This blog post was inspired by a real case we have ran into with one of our client’s project that requires alternating the two bootstrap modals. The following animation exactly replicates the problem we had to a simplest form:

Modal has background scrolling enabled which causes issues.

Although the snippets of code in this blog are AngularJS 2 and typescript, I have written this post in hopes that it will be helpful to many who are unfamiliar with them. Now lets continue…

The following describes few notes about our scenario:

  1. There are two modals currently present which are creatively named ModalOne and ModalTwo. The view of each modal will alternate at a specified button click. For example, you should be able to call ModalTwo while ModalOne is open and vice versa. The transition between ModalOne’s closing and ModalTwo’s opening should be seamless and without problem.
  2. Each respective button and modal are separated into different Angular Components. They are connected by Angular Services and Observables passing in Boolean values to signify whether to show the modal or not. This allows us to invoke the modal from anywhere in the web application at a click of the button.
  3. The Observables and Services are set up so that the modals would show and hide with the following line of code:
    // when showModal receives value 'true', modal shows itself
    this.modalOneService.showModal = true;
    
    
    // when showModal receives value 'false', modal hides itself
    this.modalOneService.showModal = false;

If you’ve had extensive experience in bootstrap, you may find that managing multiple bootstrap modals may not be so simple. Unless your goal is to open a modal that is nested inside already open modal, you may see an occurrence as if the two modals are conflicting with each other. We will review more on that topic later in this post.

Deeper into the issue

If you take a closer look inside the developer’s tool in the Chrome browser while opening and closing a single bootstrap modal, “modal-open” class is added to the body element when the modal is open and removes the class when closed.

HTML code when Modal when currently open
HTML code when Modal when currently not open

Inner-workings may be simple when dealing with a single modal but when managing multiple modals, it becomes a lot more problematic.

If you go back to the Chrome developer’s tool again while managing both bootstrap modal, you may realize that the both modal is fighting with eachother to make its respective changes to the body class with class “modal-open”. When ModalOne is to close to make room for ModalTwo, both modals fight to make its respective changes: ModalOne wants to remove the “modal-open” class while ModalTwo tries to add “modal-open” to the body element at the same time.

This is a phenomenon known as Race Condition.

So, what is race condition? This article from techtarget.com explains it the best:

A race condition is an undesirable situation that occurs when a device or system attempts to perform two or more operations at the same time, but because of the nature of the device or system, the operations must be done in the proper sequence to be done correctly.

In this case, before ModalOne has chance to close completely, ModalTwo opens and tries to add modal-open class to the <body> nearly at the same time ModalOne removes the same class. The ModalTwo’s implementation to body tag comes in after and competes/interferes with ModalOne’s change implemented few milliseconds earlier.

The most important part to take away from the definition of race condition is the following:

“…the operation must be done in the proper sequence to be done correctly”.

In this case, ModalOne should be allowed to close itself completely by completing its modal animation fully and make its changes to the <body> before ModalTwo to take action. (and vice versa).

Path to Solution

Although there is no “one-size fits all” solution to this problem as it would depend on the architecture of the app and how the modals are implemented, I hope to at least provide a guideline to help you along the way to a solution.

In the ngx-bootstrap documentation the following directives useful to this case are available. Full documentation is available here: http://valor-software.com/ngx-bootstrap/#/modals#modal-directive

onHidden This event is fired when the modal has finished being hidden from the user (will wait for CSS transitions to complete).
onShown This event is fired when the modal has been made visible to the user (will wait for CSS transitions to complete)

I will only focus on onHidden as it is the only directive we need.

The solution I have created is to implement the onHidden event to the modal:

<!-- ModalOne -->
<div class="modal fade" bsModal 
  #modal1="bs-modal"
  [config]="{backdrop: 'static'}" 
  tabindex="-1"
  role="dialog" 
  aria-labelledby="mySmallModalLabel" 
  aria-hidden="true"
  (onHidden)="hideModal()" >
.....

When the modal hides itself completely, hideModal(), will be called.

The main idea to consider is that after ModalOne is hidden, we have to differentiate in what manner ModalOne is called to be hidden:

Is ModalOne being hidden because we want to close it and go back to the main page? Or is ModalOne being hidden to switch the view to ModalTwo?

In other words, after the ModalOne has been hidden completely, we want the ModalTwo to appear ONLY when ModalTwo button is clicked. If the “x” button in the upper right corner is clicked, the ModalOne should be hidden completely with no subsequent action.

To differentiate such two actions, I have created a property modalStatus, and new methods closeModal and hideModal

/*
  If modalStatus is set true, modal is currently showing
  If modalStatus is set false, modal is currently inactive
  If modalStatus is set null, modal is closed completely.
*/
private modalStatus: any;
//(click) event binds the 'x' button of the Modal to this function
public closeModal() {
  this.modalOneService.showModal = null;
}
//this function is called when modal is completely hidden with the (onHidden) directive.

public hideModal() { 
  if(this.modalStatus!=null) {   
    this.modalTwoService.showModal = true; 
  } 
}

With the solution implemented, the switching of modal is race-condition free.

Managing Modal is now race condition free!

Thank you for making this far! While the example provided has exclusively been AngularJS 2 and above, I hope I have written this post for everyone having similar trouble. Please drop by for any questions and comments.

Thank you!

Converting your Angular CLI application into a NPM Module: Part One

Creating a custom application with Angular CLI is easy and fun. Converting your application into re-usable code is often the next logical step but can be quite a confusing process. We will discuss the process of converting your code into something you can actually use in multiple projects and distribute for others to use.

Intro

Angular CLI is a great tool to start an angular application easily and quickly. The latest version brings some great tools to the workflow like the module bundler WebPack.

Creating components and services quickly is a strong pro for the Angular CLI too, but at some point, you can only get so far with a single application. For example, you might find that you need to split some of the components into a discrete package for distribution.

Splitting your components and services into another package also has additional benefit of allowing you to consume and extend your code.

NPM

For those unfamiliar, NPM (Node Package Manager) is a JavaScript package registry that allows for easy distribution. It’s a great way to find packages and one stop place for information on updates and support. There are thousands of packages currently published and you should be very excited to add yours!

A package is defined by its config file, package.json which provides some of its meta data, the basic helper scripts and dependencies you need to run and compile your application. There is no doubt you have seen these files before. Angular CLI creates a basic package config when it creates your application and we will detail some of the steps to edit this file for distribution.

How to decide what to move from your app to a package

While every piece of code you write is likely a brilliant gem that should be printed on resume stock and handed out as examples of Great Code, likely only some of it is custom code deserves to be distributed to the masses.

Here are some questions you should ask yourself before deciding if a component or service is worthy of its own module:

  • Could this be a simple building block to solving a larger issue?
  • Do you see some of your angular code as being part of a solution to a larger issue?
  • Is this component something you or someone else will re-use on another project?
  • Does this solve a common problem you encounter?
  • Have you written code like this before and find yourself writing it repeatedly?
  • Have you written code like this before and find yourself writing it over and over again?
  • Are these collections of components unique enough that they are almost their own project?
  • Did you find the point of this application revolved around a few choice components?

Your module’s directory structure

The easiest way to explain how to create a new npm package is to show you a ‘complete’ package. Let’s look at an example below:

 ├── dist
 │   ├── bundles
 │   │   ├── ngx-foo-bar.umd.js
 │   │   └── ngx-foo-bar.umd.min.js
 │   ├── index.d.ts
 │   ├── index.js
 │   ├── index.js.map
 │   ├── index.metadata.json
 │   ├── node_modules
 │   ├── package.json
 │   └── src
 │       ├── foo-bar.module.d.ts
 │       ├── foo-bar.module.js
 │       ├── foo-bar.module.js.map
 │       ├── foo-bar.module.metadata.json
 │       ├── user.model.d.ts
 │       ├── user.model.js
 │       ├── user.model.js.map
 │       ├── user.model.metadata.json
 │       ├── user.service.d.ts
 │       ├── user.service.js
 │       ├── user.service.js.map
 │       └── user.service.metadata.json
 ├── index.html
 ├── index.ngsummary.json
 ├── index.ts
 ├── karma-test-shim.js
 ├── karma.conf.js
 ├── node_modules
 │   ├── @angular
 │   ├── @types
 │   ├── abbrev
 │   ├── ansi-align
 │   └── zone.js
 ├── package.json
 ├── rollup.config.js
 ├── src
 │   ├── foo-bar.module.ngfactory.ts
 │   ├── foo-bar.module.ngsummary.json
 │   ├── foo-bar.module.ts
 │   ├── user.model.ngsummary.json
 │   ├── user.model.ts
 │   ├── user.service.ngsummary.json
 │   └── user.service.ts
 ├── systemjs.config.js
 └── tsconfig.json

Two major directories to note in this example are: `src` and `dist`

The `src` or source directory is where you edit files and do your work. It also has its own `package.json` file that we will discuss more in depth later.

The `dist` or distribution directory is the compilation destination directory and is where we store the files we publish to npmjs. As I mentioned before we go more in-depth into this post.

Angular AOT Compiling

If you are reading this article you are most likely also aware of AOT (Ahead Of Time compilation).

For those of you who are familiar, this differs from “old school” angular compilation by doing a lot of the work that was normally done in the browser at the compilation time. Formerly this was all done by the JIT compiler where the browser would put together all the code. Now, this can all be handled by an offloaded backend process that “tree shakes” the code and trims off the fat.

Tree shaking this result in a much smaller codebase … translates to less data to send to the user … meaning faster load times!

This, of course, is a very brief introduction to the concept of AOT. For more information please review the official docs.

Ignoring some files in your Repo

There’s a lot of files that are created in the AOT build process you are not normally used to seeing in your previous JS/TypeScript projects. Make sure you do not include these in your repo or your npm package by adding these patterns to your .gitignore file:

*.metadata.json
*.map.js
*.js

Also, create a new type of ignore file called .npmignore.

*.ngFactory.ts
*.ts

Setting up your package config files for compilation and distribution

You should create two package.json files: one for development, and another for distribution. The development package file will allow you to edit and run your code for easy debugging. The production package file will allow you to distribute your smaller and compiled module to the masses.

Development package.json

Let’s take a look at an example development package.json file:

{
  "name": "my-package",
  "version": "1.0.0",
  "description": "An amazing module for Angular.",
  "scripts": {
    "transpile": "ngc -p tsconfig.json",
    "package": "rollup -c",
    "minify": "uglifyjs dist/bundles/my-package.umd.js --screw-ie8 --compress --mangle --comments --output dist/bundles/my-package.umd.min.js",
    "build": "npm run transpile && npm run package && npm run minify"
  },
  "types": "./index.d.ts",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/example/my-package.git"
  },
  "author": "Foo Bar",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/example/my-package/issues"
  },
  "homepage": "https://github.com/example/my-package#readme",
  "devDependencies": {
    "@angular/common": "~2.4.0",
    "@angular/compiler": "^2.4.10",
    ...
    "uglify-js": "^2.8.22",
    "webdriver-manager": "10.2.10",
    "zone.js": "^0.7.4"
  }
}

You will see the expected key values. Some are meta information about the package, etc.

There are some major differences in this file compared to the production package.json file: devDependencies & scripts.

NPM Package Scripts, as you know, are used to execute build & test commands and we need to install some devDependencies to allow you to work on your code.

Now let’s look at your production file…

Production package.json

You should create a production package.json file for your end users. This file should live in your `dist` directory as it’s really on. Here is an example production package.json file:

{
  "name": "my-package",
  "version": "1.0.0",
  "description": "An amazing module for Angular.",
  "main": "bundles/my-package.umd.js",
  "module": "index.js",
  "typings": "index.d.ts",
  "keywords": [
    "angular 2",
  ],
  "repository": {
    "type": "git",
    "url": "git+https://github.com/example/my-package.git"
  },
  "author": "Foo Bar",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/example/my-package/issues"
  },
  "homepage": "https://github.com/example/my-package#readme",
  "peerDependencies": {
    "@angular/core": "^2.4.0 || ^4.0.0",
    "rxjs": "^5.0.1"
  }
}

Note this file is significantly smaller than the development version. You do not need to include the devDepencies and you only point to your compiled module.

Demo-ing you Project

It’s a great idea to let end users see your package in action before they download and install it. I like to include a barebones application that implements and demonstrates my component.

This is a good way to promote your project and allows you to prove your code works.

Conclusion

We have reviewed the process of taking your code from an Angular CLI project into a fully-fledged npmjs package for others to use. We hope you can use this advice and apply it to your own projects.

We’ll explore how we ‘took apart’ one our internal Angular CLI applications and turned large portions of it into an npm package in my next post.

Thanks for reading!

Using Stubs and Mocks in Jasmine to test your Angular code

Setting up your environment and is a very important part of unit testing AngularJS code. We discuss some of the tools and methods under which we can provide the full workflow of a system under test in this post.

Intro

Unit tests allow us to automatically test our code under a variety of conditions to prove that it works and when it breaks it does so in expected ways. In order to predictably test code, we also need to completely control the setup and data provided to the code under test.

Thankfully, the test tools provided for Angular testing allow you to mimic your models and control how your code responds to code in a very precise way. Jasmine provides some easy way to create test doubles and even “spy” on their execution.

In this post we will discuss some of the best practices and tools we use to control the environment your code is working against.

Why do we need to fake stuff?

We need to control the entire environment and workflow to make sure we are testing the exact scenarios.

Messing around with the DB and creating fake records can be difficult at best, at worst it can create false positives. Even more common, some CI systems lack access to a DB at all

We also need the ability to re-create the conditions under which a bug has been created. sometimes this means we need to replicate some crazy conditions

There are two tools to make this happen: Test Stubs (also known as  Fakes, depending on who you ask) and Mock Objects:

  • Test stubs are a very simplified object or data structure designed specifically for the test scenario. These can be constructed at the beginning of the test or per test.
  • Mock objects are class instances that mimic an existing class to provide the same method interface and return specific values when a method call occurs.

Test Stubs in AngularJS & Jasmine

Test stubs are a simple data structure or model we rely on when running our tests. These can be as simple as a static array of data or a very lightweight object with publically scoped methods. To differentiate a stub from a mock, we typically only mimic the methods we are actually testing. This is quite useful during

More often than not a stub is created at the beginning of the test suites and made accessible to the suite’s tests. A good practice is to limit the modifications to the stubs to make sure you are always testing the same thing.

If you must make changes it is a good idea to make a local copy to isolates your modifications to a specific test.

Test Stub Examples

HeaderComponent

Below is an abridged version of the component code we are unit testing. The important thing to note: at the end of this method’s execution we make a call to the router service to navigate the user to the “login” route and we need to make sure this and only this method is executed.

/**
 * Simple component providing a navigation header.
 */
...
export class HeaderComponent implements OnInit {
    ...
    /**
     * clickLogout clears the user's creds but also 
     * takes the user to the Login route
     */
    clickLogout() {
        ...
        this.router.navigate(['/login']);
    }
    ...
}

Test Suite Code

Here is the abridged test suite where we create our test stub

...

/** 
 * beforeEach setup executes before each test suite test runs.
 *
 * This allows us to setup the stub before each test
 */
beforeEach(async(() => {

    ...
    
    TestBed.configureTestingModule({
        ...
        providers: [

        /**
         * Create a very basic stub object with one method:'navigate'
         *
         * Use Jasmine's createSpy to create a very basic function
         * which also allows us to "listen in" when it's called
         */
        {
            provide: Router,
            useClass: class { 
                navigate = jasmine.createSpy("navigate"); 
            }
        }
        ...
    ]})
    .compileComponents();

    ...

}));

/**
 * Here we test the method and make sure we actually navigate
 */
it('should navigate to /login when clickLogout is fired', () => {
   ...
   let router = fixture.debugElement.injector.get(Router);
   component.clickLogout();

   // "listen" to make sure that the navigate method has been 
   // called and it was called with the expected value
   expect(router.navigate).toHaveBeenCalledWith(["/login"]);
   ...
});

 

Mocks

A Mock object is a simulated object instance used to mimic a classes behavior using the same interface. In simpler terms, this is a fake class with the same method signature as the Real Thing.

A mock object can be composed of multiple objects (and sometimes multiple mock objects), but most often should be created as simply as possible to keep your tests easily maintained.

Mock Object Example

/**
 * Create a mock of an existing service
 * by simply extending it and overriding some 
 * of the methods you wish to use in your tests
 */
class MockAuthService extends AuthService {

    /**
     * This method is implemented in the AuthService
     * we extend, but we overload it to make sure we
     * return a value we wish to test against
     */
    isLoggedIn() {
        return false;
    }
}

...

beforeEach(async(() => {

    ...

    TestBed.configureTestingModule({

        ...

        providers: [

        /**
         * Inject our mocked service in place of AuthService
         */
        {
            provide: AuthService,
            useClass: MockAuthService
        },

        ...

    ]})
    .compileComponents();

    ...

}));


it('should navigate to /login when clickLogout is fired', () => {

   /**
    * Get the mocked service here from our fixture
    * and add a spyOn over-ride to pretend we have
    * a logged in user.
    */
   let service = fixture.debugElement.injector.get(AuthService);
   spyOn(service, 'isLoggedIn').and.returnValue(true);
   
});

Conclusion

Unit tests are only as good as the environment you can provide for your code under tests. It’s very important to be able to mimic and recreate the environment under which you have both positive and negative results for your code.

Unit Testing AngularJS Components & Services

Unit testing is a very important part of software development, and it is extremely important to Angular applications as they become increasingly more complex. We’ll explain how to set up your unit tests and describe what you can actually test with some examples.

Intro

Unit testing is a very important part of the software development process, especially as your applications become more and more complex. Making sure your code is robust and adaptable is an important aspect of being professional. This is no less true with your AngularJS application.

If you are reading this, you are most likely already sold on unit testing but here’s some benefits and reasons for writing and maintaining your unit tests:

  • The ability to quickly update your code and make sure you are able to regressively test your code.
  • Updating your unit tests to cover a fixed bug will prevent the bug from getting re-introduced!
  • Use a CI to make sure EVERYONE on your team is testing the code.

Angular CLI, Jasmine & KarmaJS

Here at Arroyo Labs we use the latest version of Angular CLI a lot. It’s a great way to start a project very quickly provides a great start for your application. It also gives you some boilerplate unit tests for each component and service you create using the CLI.

While we have explained Jasmine and KarmaJS in past blog articles, here is a quick overview explaining how these frameworks work together:

  • Jasmine
    • A very popular behavior driven Javascript testing framework with a very clean syntax.
  • KarmaJS
    • A framework that allows you to run your Jasmine tests on a device or headless browser. The test runner itself will provide a DOM with which your code is rendered and provides the API that Jasmine will interact with.

Setting up your tests

To create a unit test, you need to include a consistent environment in which to run your code under test and we need to control the required classes and variables that go into creating this environment. Thanks to the magic of dependency injection, we can mock up some classes used by our classes and code.

Let’s take a look at the ‘top’ portion of a unit test we use in our user-admin project (you can find the whole unit test in our repo):

/**
 * Import some basic testing classes and utilities from AngularJS's
 * core testing code. This is the minimum required code to create 
 * a basic unit test.
 */
import {
     async,
     getTestBed,
     TestBed
} from '@angular/core/testing';

/**
 * Import some specific test classes used to mock the 
 * http backend and connection classes
 */
import {
    MockBackend,
    MockConnection
} from '@angular/http/testing';

/**
 * Import the HTTP classes we use in our service
 */
import {
    BaseRequestOptions,
    Http,
    Response,
    ResponseOptions,
    XHRBackend
} from '@angular/http';

/**
 * Finally, we import the required custom classes we use in our service,
 * and the service we are testing as well.
 */
import { User }         from '../shared/models/user.model';
import { AuthService }  from './auth.service';

import { UsersService } from './users.service';

What should we test in a service?

To test a service, we have to understand the underlying concept they represent: isolating logic and code into a re-usable class. This means we have a class we can pass around in our application where we get and manipulate data in expected ways.

Keep in mind, we can really only test publically scoped variables and functions. The unit test itself is really only able to interact with your service in the same way that an application is able to.

So, we have these things to test:

  • What public variables get initialized when we create the service?
  • Do public variables update as we expect when we call public functions?

Example Service Unit Test: UserService

In our UserAdmin project, we have a service called UserService used to interact with and manipulate user data we get from the AJAX backend.

The service itself only has quite a few public methods (it’s a very important class!) so we will focus on just two of the suite’s tests of the same method `getUsers`:

getUsers should return an empty observable list when the ajax request is unsuccessful

This is a test to make sure we return an empty list of users if the AJAX response does not contain an encoded list of users. This is a negative test, we are making sure that we return an expected response even when the backend returns an error.

it('#getUsers should return an empty observable list when the ajax   request is unsuccessful', () => {

 // set up the mocked service to return an
 // unsuccessful response (no users, 500 status)
 // with a helper method
 usersBodyData.success = false;
 setupConnections(backend, {
     body: {
         body: usersBodyData // use the previously init'd var for consistent responses
     },
     status: 500
 });

 // set up our subscriptions to test results 
 // when we actually get a result returned
 service.users$.subscribe((res) => {
     if(res) {
         expect(res).toBeTruthy();
         expect(res.length).toEqual(0);
     }
 });

 service.total$.subscribe((res) => {
     if(res) {
         expect(res).toBeTruthy();
         expect(res).toEqual(0);
     }
 });

 // make the actual request!
 let res = service.getUsers();

});

getUsers should return an observable list of users and result total when the ajax request is successful

This test makes sure that we get an observable list of users if the AJAX response is successful. To make sure this happens, we mock the response as though we have a JSON encoded list of users.

it('#getUsers should return an observable list of users and result total when the ajax request is successful', () => {
 // set up the mocked service to return an
 // unsuccessful response (users, 200 status)
 // with a helper method
 setupConnections(backend, {
 body: {
 body: usersBodyData
 },
 status: 200
 });
 
 // set up our subscriptions to test results 
 // when we actually get a result returned
 service.users$.subscribe((res) => {
 if(res) {
 expect(res).toBeTruthy();
 expect(res.length).toEqual(2);
 }
 });
 
 service.total$.subscribe((res) => {
 if(res) {
 expect(res).toBeTruthy();
 expect(res).toEqual(2);
 }
 });
 
 // make the actual request, with some params to pass via query string
 // we will explore this in a future post
 let res = service.getUsers(42, 42, 'id', 'desc');
});

What should we test in a component?

A component, like a service, is also a re-usable piece of code but it also has a defined lifecycle from its parent class and a frontend element via it’s template and optional CSS.

So, here is what we have to test:

  • Does this component actually get constructed?
  • What public variables get initialized and what DOM elements get rendered when we create the component?
  • Do public variables update as we expect when we call public functions?

Like we have noted above when discussing testing a service, you can really only test things that have been scoped as public by the component itself. This does include rendered DOM elements and you should test that these elements appear and render as expected since these are made public by the component itself.

Example Component Unit Test: UserListComponent

Test that the component actually results in a rendered component

it('should create', () => {
   fixture.detectChanges();
   const compiled = fixture.debugElement.nativeElement;
   component.ngOnInit();
 
   component.users = [];
   component.total = 0;
 
   // do we have a component at all?
   expect(component).toBeTruthy();
 
   // create new user button
   expect(compiled.querySelector('.btn-info')).toBeTruthy();
 
   // do we have a table
   expect(compiled.querySelector('table')).toBeTruthy();
   expect(compiled.querySelectorAll('tr').length).toBe(2);
});

Test that we display a list of users with a mocked response

it('should display list of users', () => {
   fixture.detectChanges();
   const compiled = fixture.debugElement.nativeElement;
 
   setupConnections(backend, {
       body: {
           body: bodyData
       },
       status: 200
   });
 
   component.ngOnInit();
 
   // create new user button
   expect(compiled.querySelector('.btn-info')).toBeTruthy();
 
   fixture.detectChanges();
 
   // do we have a table with users?
   fixture.detectChanges();
   expect(compiled.querySelectorAll('tr').length).toBe(21);
 
   // do we see the expected page count
   expect(component.getPageCount()).toBe(2); 
});

Conclusion

Unit testing is a not a oft-celebrated portion of the software development cycle, but it is an important part of the process. Once you have good tests in place, you can pivot direction and update your code with an increased sense of security.

Angular 2 VideoJS Component

Using components is a fantastic way to include 3rd party libraries like VideoJS in your Angular 2 application.

We have talked previously about the basics and different types of Angular 2 components, but today we will give you a practical example of using Angular components to wrap an external library. We will focus on the excellent video media player library VideoJS, but this can really be applied to many other libraries as well.

Using external libraries in Angular 2

To actually use some 3rd party libraries within an Angular 2 application, you need to jump through some hoops. Most libraries require direct access to the DOM model and expect full control of the DOM rendering cycle. Part of the magic of Angular 2 is ceding some of that control to allow it to render when it feels like it.

To get around this hurdle you simply need to wrap your 3rd party libs in a way that gives more control to Angular and allows the 3rd party library access to the DOM via the application lifecycle.

Most 3rd party libraries, like VideoJS, would have been wrapped in a directive in previous versions of Angular. In our example we will use a component, but it is possible to use a pipe or a service depending on your 3rd party library.

VideoJS

VideoJS is a (rightfully) popular media player library that makes it easy to skin and control media files. This library can handle many types of media files like MP4s, MOVs and even YT (with a plugin).

Videos have traditionally been a tough element to render consistently across browsers. Given the rather recent support for the HTML 5 video element things have gotten better, but it has always been a little tough to consistently style the player itself. VideoJS both abstracts out the skin and API hooks which make things much easier than in the past.

One of the reasons we chose this library for our example is that it’s pretty self contained. It does not require external libraries like jQuery and is also relatively small.

VideoJS Component

Check out this plnkr to see the example VideoJS component.

First things first: include the VideoJS library assets in the application HTML head so we can use it with our component.

<link href="https://vjs.zencdn.net/5.11/video-js.min.css" rel="stylesheet">
<script src="https://vjs.zencdn.net/5.11/video.min.js"></script>

Our example component is pretty simple, lets take a look at some of the component code itself:

The template code

  <video *ngIf="url" id="video_{{idx}}"
     class="video-js vjs-default-skin vjs-big-play-centered vjs-16-9"
     controls preload="auto"  width="640" height="264">
     
    <source [src]="url" type="video/mp4" />
   
  </video>

This is a pretty simple template, and really only consists of a video element with some CSS classes and a source element.

Some things to note in the template code itself:

Prevent rendering the element itself unless we have a video URL:

*ngIf="url"

Add a unique index to make sure we can reference this element alone:

id="video_{{idx}}"

Add a `source` element for the video url itself:

<source [src]="url" type="video/mp4" />

Initialize the Player in ngAfterViewInit

We need to wait until the component template is rendered before we can let VideoJS do it’s magic. In order to let Angular tell us when the component’s lifecycle has reached that point we use a specific event hook called ngAfterViewInit that fires when the component template has been been completed.

Check out the code below to see this in action:

  ngAfterViewInit() {
    
    // ID with which to access the template's video element
    let el = 'video_' + this.idx;
    
    // setup the player via the unique element ID
    this.player = videojs(document.getElementById(el), {}, function() {
      
      // Store the video object
      var myPlayer = this, id = myPlayer.id();
      
      // Make up an aspect ratio
      var aspectRatio = 264/640;
      
      // internal method to handle a window resize event to adjust the video player
      function resizeVideoJS(){
        var width = document.getElementById(id).parentElement.offsetWidth;
        myPlayer.width(width).height( width * aspectRatio );
      }
      
      // Initialize resizeVideoJS()
      resizeVideoJS();
      
      // Then on resize call resizeVideoJS()
      window.onresize = resizeVideoJS;
    });
  }

Component Element

Include the VideoJS component in your component:

<videojs [idx]="idx" [url]="video"></videojs>

If you check out our plnkr you can see this on the app.ts you can see we support multiple video elements as well.

Conclusion

Components are a great way to help separate your coding concerns, and are a major building block in creating an Angular 2 application. They are also great to encapsulate and add some sanity to 3rd party libraries that you wish to use in your projects!
If you have any comments concerns or questions, please let us know in the comments!

[Update 06/12/2017]

I have updated the plnkr code to show how to properly import the VideoJS library into your component. Thanks for the feedback!

Introducing the Erdiko User Admin

Introducing the Erdiko User Admin Package! A user administration package built with an Erdiko powered backend and a Angular 2 frontend.

We’re excited to introduce the Erdiko User Admin! A modular package that provides an attractive UX to allow you to manage your users.

This is still very much a work in progress, but since we’re so excited, we want to let everyone know about this project (and request some help to keep us moving).

Check out our User Admin Project at this Github Repository and our Packagist entry.

Project Features

We wanted to create a modular and simple User Admin you can ‘bolt-on’ a new or existing project. We keep this as lean and mean as we could, but still providing some cool stuff to help get you started.

While this package is still very much in development, it does provide some of the following features:

  • A sortable and paginated list of user records.
  • An attractive user interface allowing the user to create, edit & delete user records
  • JWT user authentication!

Here’s some screenshots of our UX:

Installation and Setup

The User Admin package is a part of the Erdiko module ecosystem. Installable and upgradable via Composer. This makes it very simple to start a new project via this simple command.

composer create erdiko/user-admin [PROJECT NAME]

Please note that as of this time, we have not created an official release. You will need to include the minimum stability flag when you create your project:

composer create erdiko/user-admin [PROJECT NAME] --stability DEV

Package Dependencies

Here’s a brief list (and a bit of a plug) of some of the other Erdiko Packages we as a team have been developing that we use to build this project. While we use these packages for our development, we have planned to make these as modular and replaceable as we can.

Here’s the list:

  • erdiko/core
    • The base package that provides our basic routing and templating.
  • erdiko/authenticate
    • Authenticate the user’s credentials to assert they are who they say they are.
  • erdiko/authorize
    • A package that helps us enforce some user roles.
  • erdiko/users
    • Our Erdiko package that provides the backend storage and basic routes we use to interact with these models.

AngularJS 2

We utilize the great Angular CLI project to start and maintain the Angular code itself. This project was a great boon to help us get started on a well structured and maintainable Angular application.

The internal structure is “just” a simple app, but we have updated the NPM script to compile and move the resulting files to an directory accessible to the Erdiko application Home route.

NPM Run Scripts

Here is a quick list and an explanation of some of the custom NPM run commands we have for this project.

  • Start the local Angular Development server: npm run start
  • Run the unit tests: npm run test
  • Run the e2e/functional tests: npm run e2e
  • Compile and export files for end user: npm run build

Next Steps

Here’s an incomplete list of some of the next things we plan on working on, and completing, with the project in the future:

  • Jasmine Unit Tests to cover our angular code
  • KarmaJS Functional Tests to cover the entire application end-to-end
  • A basic User facing profile designed for user extension

How to Contribute

If you have an idea for a new feature, have an idea on how to improve a feature, or (gasp) you have found a bug please report this on our Github Repo Issues page.

However if you are just excited about this project, feel free to “star” this repo on Github to show your support.

We would also love to know if and how you use this module in your own projects!

To set your environment up for local development, please follow these steps:

  1. Clone your fork of the User Admin project into a local directory
  2. Clone the following packages into the same directory
  3. Copy the composer-dev.json file to composer.json
  4. Start your docker container docker-composer up --build

Conclusion

Thanks for reading about our exciting new package! Feel free to leave a comment or ask questions below, or feel free to comment on our Github Repo page!

Angular 2 Animations

Animations are a very important part of User Experience design for web applications. We’ll will explore how animations are created and configured in Angular 2 and provide some concrete examples.

Introduction

Continuing on our series of Angular 2, we’re now going to explore  animations in Angular 2. Clearly smooth animation and transitions are an important part of the UX design for interactive applications.

Let’s start off by talking about how we animated things in Angular 1.x.

Animations in Angular 1

Angular 1.x allowed for animations between states for a handful of directives and elements, which when coupled with the nature of an Angular application, presented some great results. Two methods were provided to allow the user to add these transition states: CSS and Javascript. While both methods had some pros and cons, it also led to different interfaces that could easily confuse a developer.

CSS transitions were provided simply by using CSS3 transitions, which have the benefit of not requiring additional JS libraries and are as fast as your browser can render. Most of the control of this style of animation is controlled by using a unique class name structure and Angular handles a class change based upon a unique naming scheme.

The ngAnimate module provided a Javascript interface to control animations. This module allowed the user to use (most likely) jQuery’s animation controls or a 3rd party JS lib to render animations. This has some benefits of allowing some fine grain control, but you were also limited to what the 3rd party library allowed you.

Animations in Angular 2

Angular 2 uses the Web Animations API to really let your browser control animations with the highest possible performance and timing control.

Unlike Angular 1.x’s interface, the entire animation library is contained within a single module. This allows for a common simple interface, but since it uses the Web Animation API, also allows the browser to optimize the animation control to a finer control that previously allowed by CSS3 only animations.

While I should note that this also requires a compatible browser to run these animations, there is a polyfill available to cover legacy browsers that is easily installed.

Let’s explore some of the basic concepts used for defining and controlling Angular 2 animations.

Triggers

Triggers are the term for a function that defines the states and transitions used for an animation. These are defined in the component annotation metadata fields and have a corresponding placement on a component’s template to indicate where an animation is applied when the end user interacts with the application.

Here’s an example of triggers defined in a simple component, and explains where we put the settings we explain later in this post:

animations: [
  trigger(
    'pState', 
    [
      state('inactive', style({
        transform: 'scale(.9)'
      })),
      state('active', style({
        fontWeight: "bold",
        transform: 'scale(1)'
      })),
      transition('active => inactive', animate('50ms ease-out')),
      transition('inactive => active', animate('50ms ease-in'))
    ]
  )
]

States

States are a defined condition, or a specific point in time by, that you can define in your Angular 2 component via a string. These finite conditions allows you to define a value you can pass into your components template to help set up your animation conditions. Examples of these states are “active” and “inactive” that can identify an element that is “On”. See our first example for a demonstration of these states.

Timing

Timing in Angular 2 is defined by three properties: duration, delay and easing

Duration controls how long an animation runs. Defined by a string or an integer in milliseconds or seconds, it’s never been easier to define the length of time a transition occurs. Here’s an example of a duration of two seconds “2s” and 200 milliseconds “200ms”.

Delay, much like you assume, is about the time that elapses between the trigger execution an the start of the animation. You can even define the delay in the same line you define the duration in this example where it last two seconds after a delay of 3 seconds: “2s 3s”

Easing is how angular controls the animation accelerates and decelerates during it’s runtime and is a pretty succinct way to add some ‘realism’ to your animation. Identified by a string, these have the same common names as the control parameter in CSS3. Some more information can be found here on this site, easings.net.

Callbacks

Callbacks are just methods called when an animation starts and stops. This is useful for executing code based on an animation’s timing, and if you have ever tried to chain commands together using browser timing alone, you will seriously jump for joy.

Here’s an example from the official angular guide with the callback methods “animationStarted” & “animationDone”:

...
  <li>
    (@flyInOut.start)="animationStarted($event)"
    (@flyInOut.done)="animationDone($event)"
    [@flyInOut]="'in'" >
    {{hero.name}}
  </li>
...

 

Example 1: P Tag State on Button Click

Our first example shows hows we can animate the two states (Active & Inactive) of a displayed P tag. Keeping this simple, we illustrate how to set up a component to use the animation library and how to set up two simple states and their transitions.

Click the gif of the plnkr below to see the code in an active plnkr:

ex_1-p_tag

Example 2: Multi-Step Animation with Callbacks

Our second example shows a multistep animation that uses keyframes to add multiple steps to a transition, and callbacks that output the start and end of each animation to the console.

Check out this plnkr, and open your console, to see this in action:

ex_2-multi-step

Conclusion

Animations add so much to web applications that it’s a mistake not to include them. Thankfully Angular 2 makes this easier to include and trigger your animations with minimal work from the developer.

Angular 2 Attribute Directives

Attribute Directives are a powerful way to affect the appearance or behavior of a DOM Element in your Angular 2 Application. We examine how attribute directives work, and how you can build re-usable custom code for your projects.

Introduction

AngularJS really introduced the concept of organizing and extending the DOM for use in real web applications. AngularJS 1.x brought us the idea of a Directive, or a way to indicate that a DOM element was “special” and will have a behaviors or an appearance that will be controlled by your code. AngularJS 2 took this idea and ran with it, but this also means we need to explain some stuff. We now have 3 tools at our disposal for interacting with the DOM: Components, Structural Directives and Attribute Directives.

Components, which you should have at least read about by now, are the most basic of the angular building blocks. Everything is a component and all components have directives; components are created from one or more directives. Directives are the method to identify a component’s behavior or associate a variable to a component.

Structural Directives are used to add or remove elements from the DOM. Common examples are *ngIf or *ngFor. These directives allows you manipulate a component based on a variable value or allow a component to iterate a series of values.

Finally, we have Attribute Directives. Attribute directives allow you to attach a behavior to an element or affect it’s appearance and re-use this throughout your application or package it up as something you use in all your projects.

Using Attribute Directives you can create a stylized DIV tag that formats all text and adds an event listener to change the color when the user mouses over the text. Show off your example code with some syntax highlighting!

I should also note that Attribute Directives can access and manipulate application values, but primarily are focused on affecting the component they have been attached. Think of this as more like CSS Selector Class on steroids. Make sure you do the “real math” of your application in your components.

Anatomy of an Attribute Directive & How to use it

Attribute Directives can be simple or complex. The simplest example of an Attribute Directive could be a simple CSS property attached to a P Tag:

<p [style.background]="'red'">I'm red!</p>

Anything more complex than the above example requires a little more wiring. Let’s look at an commented example from the official docs called “Highlight”:

// Import some stuff from the core library
import { Directive, ElementRef, Input, Renderer } from '@angular/core';

// create a Directive to decorate. To prevent confusion let's call this myHighlight to 
// illustrate the fact this this is a custom appearance
@Directive({ selector: '[myHighlight]' })

export class HighlightDirective {

    /* 
    This is a pretty simple example, we just need a constructor. Pass the element we wish to affect in as "el" and make sure we interact with the DOM renderer with the obvious name of "renderer"
    */
    constructor(el: ElementRef, renderer: Renderer) {

       /* 
       Set the element's Background Color CSS property to Yellow, as though we "highlighted" it with a marker.

       Note we reference the element itself as el.nativeElement so we actually update the rendered DOM model itself.
       */
       renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'yellow');
    }

}

Use and apply your custom directive attribute in your application

<p myHighlight>Highlight me!</p>

Some Attribute Directive Examples

Italic & Underline

A very simple example showing how we can make something italic, and underlined, using a simple attribute directive.

@Directive({ selector: '[alItalic]' })

export class ItalicDirective {
 
  constructor(el: ElementRef, renderer: Renderer) {
    renderer.setElementStyle(el.nativeElement, 'fontStyle', 'italic');
    renderer.setElementStyle(el.nativeElement, 'textDecoration', 'underline');
  }
 
}

Plnkr

Blink

We can also bring back the much missed BLINK tag using an attribute directive. This example illustrates how we can actually encapsulate some logic and manipulate the DOM element’s CSS with this logic by using an attribute directive that can be placed on any block element.

@Directive({ selector: '[alBlink]' })

export class BlinkDirective {
  
    constructor(el: ElementRef, renderer: Renderer) {
      setInterval(() => { 
        let style = "hidden";
        if(el.nativeElement.style.visibility && el.nativeElement.style.visibility == "hidden") {
          style = "visible";
        }
        renderer.setElementStyle(el.nativeElement, 'visibility', style); 
      }, 750);
    }
    
}

Plnkr

Detected User Event – Click

Finally, here’s an example where we can listen for a user event (click) on an element by simply using an attribute directive.

import { Directive, ElementRef, Input, Renderer, HostListener } from '@angular/core';

@Directive({ selector: '[alClick]' })

export class ClickDirective {
  
  private _el: ElementRef;
  
  constructor(el: ElementRef, renderer: Renderer) { 
    this._el = el;
  }

  @HostListener('click') onClick() {
    let str = this._el.nativeElement.innerHTML;
    alert("innerHTML from the element you clicked: " + str);
  }
    
}

Plnkr

Conclusion

We really only scratched the surface of what you can do with Attribute Directives. AngularJS has always been a framework that allowed you to organize and extend your DOM based applications, but AngularJS 2 has taken this to a whole new level.

Hope you enjoyed this post!

Angular 2 Pipes

Angular 2 pipes replaced filters as a method to format and manipulate text for output. We explore some background behind pipes and provide some simple examples to explain these concepts.

Introduction

Pipes are a feature of Angular 2 that allows you to contextually manipulate and format text on the front end. From simple date formatting, to a complete transformation, pipes allow you to separate how you display data provided from the backend.

Prior to Angular 2, text transformation was provided by “filters”. Conceptually the same in usage, Angular 2 gives us a little more power and flexibility to how we can package up the text manipulation power of these smaller components.

Commonly used & built in Pipe examples

Some pipes merely intake a string and return a formatted result, others take parameters to help construct the resulting output.

The best part of using these are literally built into the framework. No extra file library inclusions are required.

UpperCasePipe & LowerCasePipe

UpperCasePipe & LowerCasePipe are two built in pipes that allow you to transform text, as their names would imply, before outputting to the DOM.

These are the most simple of pipes (and really, could be replace with some CSS) but they illustrate the mechanic: The value you wish to transform goes on the left a “pipe” (this “|” character) and then the transformative function goes on the right.

Here are two quick examples:

<p>{{ firstname | lowercase }}</p> // Foo -> foo 
<p>{{ lastname | uppercase }}</p> // Foo -> FOO 

Pretty simple, and lets us explain some more complex setups.

DatePipe & CurrencyPipe

There are also some slightly more complex built in pipes, some of which take in full objects, other take expressions from which to transform the text they transform.

DatePipe

DatePipe formats and transforms a Date object into a string based on a provided expression and locale rules.

Here are some example DatePipe usages with some of the build in expressions:

<p>{{ now | date }}</p> // Nov 15, 2016 
<p>{{ now | date:'medium' }}</p> // Nov 15, 2016, 12:05:08 PM 
<p>{{ now | date:'M-d-y' }}</p> // 11-15-16

CurrencyPipe

Like the DataPipe, CurrencyPipe also formats using a provided express and based on the browser’s locale. I’ll leave you to check the official documentation, but this is a very basic example.

<p>Total: {{ total | currency:'USD':true:'4.2-2'}}</p> // $10.99

Creating Custom Pipes

Creating custom pipes can be a little scary and intimidating at first, but is not hard in principle. We’ll walk you through the basics and provide a few examples to work from.

Structure and formatting your Pipe definition

Creating a pipe is pretty easy, in fact it looks like how you create an angular component. Let’s break down this example:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'foobar'})
export class FooBarPipe implements PipeTransform {
 
    transform(value: string, args: string[]): any {
        return "FooBar" + value;
    }
 
}

After including the Pipe & PipeTransform libraries from angular/core, you simply need to use the @Pipe decorator. The decorator accepts a parameter called “name” which is used to reference your custom pipe in your template code.

Finally, your pipe must implement a method called “transform” which, coincidentally, transforms your provided text or object.

And including into your app module is also quite simple:

import { FooBarPipe } from './foobar.pipe';

...

@NgModule({
 imports: [ BrowserModule ],
 declarations: [ App, FooBarPipe ],
 bootstrap: [ App ]
})
export class AppModule {}

Parameters

As we noted previously, you can also pass parameters to a pipe to affect the how the value piped in is transformed. You can send multiple parameters as well each separated by a colon (“:”) and extract them in your transform method.

Example 1: Prefix “FooBar” to a provided string

This is a simple example of a custom pipe that prefixes “FooBar”:

Example 2: Multiply a provided integer by Number

Show an example where we multiply the output by 42 (provided by the component) and return a result. This will illustrate the idea of stateful pipes.

Example 3: Convert string to Pig Latin

Here is an example of a pipe that converts a provided string to Pig Latin.

Conclusion

Pipes are a useful and easy to learn concept in angular 2. While it’s easy to think they are limited to formatting and displaying text, we have also shown some re-usable examples where a company can have a small arsenal of pipes at their disposal.

Angular 2 Routing

Angular 2 Routing is bit complicated when compared to routing in Angular 1.x but it is very powerful. We hope to clear up some of the common confusion when setting up routing and provide some practical examples as references.

Understanding routing in you application is the key to creating a single page application. Routing is what allows view navigation in your application like ‘detail views’, end user bookmarking and even allows you to set up a ‘logged in’ version of your applications views.

Routing isn’t included by default in Angular 2, in fact you have to explicitly include it as a library. I also will say, it’s not incredibly intuitive to configure. We’ll take some time to explain the history of the router and dive into some of the basic concepts.

Basic Concepts of Routing in Angular 2

Router Library

The router itself is implemented in the optional Router Module, which is kept separate to keep the base library size low. Include it in your main module like this:


import { RouterModule } from '@angular/router';

...
@NgModule({
 declarations: [ ... ],
 imports: [
     RouterModule.forRoot(routes),
     ...
 ],
 providers: [ ... ],
 entryComponents: [AppComponent],
 bootstrap: [AppComponent]
})
export class AppModule {

}

Base HREF

The base HREF is the starting point for your application and is used to create your home route. It’s this starting point that your browser will also use to create a history to prevent ‘breaking the back button’ which is always a sticking point in SPAs.

Here’s the syntax you need to add to you html:

<base href="/">

Configuration & Routes

const routes = [ 
    // Default, or home, path. This matches your Base HREF
    { 
        path: '', 
        component: HomeComponent 
    }, 

    ...

    // Wildcard, or the 'catch-all' route pattern. If the requested
    // route does not match anything above, this route is displayed.
    { 
        path: '**', 
        component: HomeComponent 
    } 
];

Resolves & Guards

Resolves are services that must be completed before allowing the route to be accessed and loaded. This is how we can ensure that the data is available for the route prior to allowing the user to access the route.

A quick example of this would be a UserResolve class that retrieves a list of users before displaying the route.

Guards are a method to prevent a route from being accessed unless a certain state is met.

A quick example of this would be a LoggedInGuard class that prevents a user from accessing a route unless they are logged in.

Child Routes

Child routes are a way to add specific routes to a feature.

Example 1: A One Route Application

Below is an example of an application with a single route. This illustrates including the router module, a base href and a very basic route configuration.

Example 2: A One Route Application with a Resolve

Below is an example of an application with a single route that requires a service to resolve a data retrieval before rendering.

Example 3: A multiple route application with a child route

Below is an example of an application with two routes and a child route.

Conclusion

While it may take some time to completely wrap your mind around routing in angular it’s clearly an important part of creating a real SPA. Don’t be afraid to take and reference your own notes!