<![CDATA[ShMcK]]>Blog]]>http://localhost:2368/Ghost 0.6Tue, 12 May 2015 07:02:59 GMT60<![CDATA[Component Router Lifecycle Hooks]]>Part 2: Component Router Lifecycle Hooks

& Using ES6 classes in Angular 1.x


In part 1 we looked at how router conventions help you stay organized and write less code.

Note: Component router is still in development & only available for Angular 1.3+

Now we'll look at something

]]>
http://localhost:2368/component-router-lifecycle-hooks/995be51b-7411-4731-809c-2e1518204fd6Wed, 06 May 2015 13:09:55 GMTPart 2: Component Router Lifecycle Hooks

& Using ES6 classes in Angular 1.x


In part 1 we looked at how router conventions help you stay organized and write less code.

Note: Component router is still in development & only available for Angular 1.3+

Now we'll look at something much more awesome. Using a multi-step form as an example, we'll see why you should take advantage of ES6 classes in Angular, and look at how to use component routers Lifecycle Hooks.


Project

Here's the scenario: you have a multi-step user sign-up form, and you want to save the user data whenever there is a route change.

First we'll need a service to save the data.

ES6 Classes as Services

This service will save our user form data to UserService.user.

We can use UserService.save(updates) to merge new form data objects with our user. For example, if our user has existing data, {name: 'Joe'}, we can push more updates {age: 24} to make a complete user object {name: 'Joe', age: 24}.

class UserService {  
  constructor() {
    this.user = {};
  }
  save(updates) {
    function update(obj) {
      for (var i = 1; i < arguments.length; i++) {
        for (var prop in arguments[i]) {
          var val = arguments[i][prop];
          if (typeof val === 'object') {
            update(obj[prop], val);
          } else {
            obj[prop] = val;
          }
        }
      }
      return obj;
    }
    update(this.user, updates);
    // a Promise could be used here, returning false if there is an error. 
    return true;
  }
}

export default angular.module('app.services.user', [])  
  .service('UserService', UserService);

ES6 Classes as Controllers

Why use ES6 classes as controllers? Inheritance.

But first, let's make our UserFormCtrl and inject the UserService we just made.

export class UserFormCtrl {  
  constructor(UserService) {
    this.user = UserService;
    // bind ng-model to this.user
  }
}
UserFormCtrl.$inject = ['UserService'];  

This is what we want all our User Form controllers to inherit from.

LifeCycle Hook: canDeactivate

The Component router has a cool new feature called lifecycle hooks. These are functions that can be run during phases of routing, they include:

  • canActivate
  • canDeactivate
  • deactivate
  • activate

I'll encourage you to read more about these hooks, but for the sake of brevity, let's focus on what we need.

We want the form to save before the route changes, so we're looking at the canDeactivate hook.

Let's adjust our FormCtrl class.

UserFormCtrl.prototype.canDeactivate = function () {  
  return this.User.save(this.form);
  // true = continue
  // false = stay with the current route. change fails.
};

Now we have a class UserFormCtrl that will save on route change to our UserService.

Extending an ES6 Class

We can now create a series of multi-step form views with corresponding controllers.

class UserProfileCtrl {}  
class UserDescriptionCtrl {}  
class UserGoalsCtrl {}  
//
export default angular.module('app.user.form', [])  
.controller('UserProfileCtrl', UserProfileCtrl)
.controller('UserDescriptionCtrl', UserDescriptionCtrl)
.controller('UserGoalsCtrl', UserGoalsCtrl);

These form controllers can gain the ability to save to UserService through inheritance.

class UserProfileCtrl extends UserFormCtrl {}  
class UserDescriptionCtrl extends UserFormCtrl {}  
class UserGoalsCtrl extends UserFormCtrl {}  

In the view, bind your forms to the model this.user from UserFormCtrl and everything should work. Forms will be saved on route changes.

<input type="text" ng-model="vm.user.password">

<a ng-link="userDescription">  
  <button>Next</button>
</a>  
<!-- note: ng-link requires the a tag -->  

Conclusion

There are good reasons to use ES6 Classes for controllers and services rather than just functions. It's not just a style decision.

Also bear in mind, this is only scratching the surface of what you can do with the Component router's lifecycle hooks. These hooks are a great reason to try out the new router today.

]]>
<![CDATA[Angular Component Router]]>Part 1: Component Router Conventions



The new-angular-router coming with Angular 1.3+ now has a name: Component router.

The Component router is aptly named, as it is designed to help break your project into components (such as directives).

Here's a brief overview of some structural changes:

  • It routes to components
]]>
http://localhost:2368/component-router-conventions/878c7d4f-c1da-47ca-ae98-901c84e01afbWed, 06 May 2015 12:15:24 GMTPart 1: Component Router Conventions



The new-angular-router coming with Angular 1.3+ now has a name: Component router.

The Component router is aptly named, as it is designed to help break your project into components (such as directives).

Here's a brief overview of some structural changes:

  • It routes to components (directives), not templates/controllers
  • The routes are setup in a controller/class, not during a config phase
  • It uses default conventions to find templates & controller names

Let's take a look at comparison between the three popular routers in Angular: ngRouter, uiRouter, & the new router.

ComponentRouterComparison

In this post, we'll look how naming using the Component router with naming conventions can help save you a lot of code.


Conventions

Conventions mean less code. But the magic behind the scenes, that is, the default template mapping and controller naming, can initially come with a lot of confusion.

Let's make a comparison with ui-router to see the repetition Component router is trying to avoid.

ui-Router Example

The popular ui-router is based on states.

  $stateProvider
      .state('abc', {
        url: '/abc',
        templateUrl: 'app/templates/abc.html',
        controller: 'AbcCtrl as vm'
      });

But not DRY enough (Don't Repeat Yourself). This method uses too much chalk.

Component Router Example

Component router comes with built in defaults of how to structure and find your code.

The router defaults assume where the template is located and what the controller will be named.

$router.config([{
      path: '/abc',
      component: 'abc'
}]);

Component router makes the following assumptions based on the component name.

  • templateUrl: '/components/abc/abc.html',
  • controller name: 'AbcController'
  • controllerAs: 'abc'

If you're using compound names, Component router uses snake-case for templates & camelCase for scripts.

$router.config([{
      path: '/defGhi',
      component: 'defGhi'
}]);
  • templateUrl: '/components/def-ghi/def-ghi.html'
  • controller name: 'DefGhiController'
  • controllerAs: 'defGhi'

To keep things easy, just organize your components in the components folder by a snake-cased name. Everybody's happy.

Not happy? If you're not going to let a router tell you how to organize your code, read on. Otherwise, you can leave it at that.

Editing Conventions

These conventions can be edited to your own liking use the $componentLoaderProvider. It's a provider, so run it in the .config() stage.


Change Controller Name

Perhaps you like to name your controllers. You can use the $componentLoaderProvider.setCtrlNameMapping function which takes the component name and returns the new default controller name.

Controller: CapitalizedCtrl

.config(function($componentLoaderProvider) {
      $componentLoaderProvider.setCtrlNameMapping(function (name) {
            // where name is the component name
            var capitalized = name.charAt(0).toUpperCase() + name.slice(1);
            return capitalized + 'Ctrl';
      });
}

The path to your templates can be changed using the $componentLoaderProvider.setTemplateMapping function which takes the component name and returns a path to the default template.

Template: states/component-name.html

.config(function($componentLoaderProvider) {
      $componentLoaderProvider.setTemplateMapping(function(name) {
            var snakeCased = name.match(/[A-Z]*[^A-Z]+/g).join('-');
            return '/states/' snakeCased + '.html';
  });
}

Conclusion

The Component router keeps your code DRY, forcing you to design your app in components, maximizing your use of directives, and using common conventions. It can be frustrating to get started with the Component Router without knowing the defaults, but personally, I've grown to appreciate it.

In part 2 we'll look into using Component router's lifecycle hooks to work some magic, as well as how to take advantage of using ES6 class inheritance.

]]>
<![CDATA[Webpack & Angular: Part 3]]>Part 3

6 Ways to use Webpack Require with Angular

Webpack & Angular

For some reason, Webpack & Angular reminds me of late 90s Acne commercials.

It keeps your code: clean, clear & under control

What a terrible way to start a blog post, but I'll stick with it. No regrets.

In Part

]]>
http://localhost:2368/webpack-angular-part-3/b441f294-d947-46c5-91ad-2d3f80b417a2Wed, 15 Apr 2015 02:37:27 GMTPart 3

6 Ways to use Webpack Require with Angular

Webpack & Angular: Part 3

Webpack & Angular: Part 3

For some reason, Webpack & Angular reminds me of late 90s Acne commercials.

It keeps your code: clean, clear & under control

What a terrible way to start a blog post, but I'll stick with it. No regrets.

In Part 1 & Part 2 we prepared setting up the project, all for this moment. Let's take advantage of using Webpack & Angular for creating modular code.

What is Required

In this demo we'll keep it simple and make a navbar directive, looking at the different ways of using require.

1. require('module').name

First of all, we'll need a module for handling our layout directives.

/app/core/layout.js

export default angular.module('app.layout', [])  

We can simply require the layout by its (path).name, allowing us to change module names at any time.
Just make the loaded module a dependency.

/app/index.js

module.exports = angular.module('app', [  
  /* 3rd party */
  'lumx',
  /* modules */
  require('./core/layout').name
]);

2. Modular Directive Names

This makes it easy to change directive names in separate files with ease.

Let's start by setting up the navbar template.

/app/core/nav/nav.html

<header class="header bgc-light-blue-600" ng-cloak>  
<!-- Get the app info and put it in the navbar on the left -->  
  <h1 class="main-logo">
    <a href="/" class="main-logo__link" lx-ripple="white">
      <span class="main-nav--title">{{::nav.app.title}} </span>
      <span class="main-nav--version">v{{::nav.app.version}}</span>
    </a>
  </h1>
<!-- Loop over the links and add them to the navbar on the right -->  
  <nav class="main-nav main-nav--lap-and-up">
    <ul>
      <li ng-repeat="n in nav.app.links">
        <a href="{{::n.link}}" class="main-nav__link" lx-ripple="white">
          {{::n.text}}</a>
      </li>
    </ul>
  </nav>
</header>  

Add some style:

/app/core/nav/nav.scss

.header {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 999;
  height: 60px;
  padding: 12px;
  color: white;
  background-color: #4fc1e9;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

For the full nav.scss file, get it on Github. This is a short/ugly version.

Next add the directive & controller. Don't be confused, in this case my controller uses ES6 classes.

/app/core/nav/nav.js

class NavCtrl {  
  constructor() {
    this.app = {
      title: 'Module Loaders',
      version: '0.3.0',
      links: [{
        text: 'Webpack',
        link: 'http://webpack.github.io'
      }, {
        text: 'Require.js',
        link: 'http://requirejs.org/'
      }, {
        text: 'Jspm',
        link: 'http://jspm.io/'
      }]
    };
  }
}
export default () => {  
  require('./nav.scss');  // load styles for the component
  return {
    controller: NavCtrl,
    controllerAs: 'nav',
    templateUrl: './core/nav/nav.html'
  };
};

Notice the directive was never named. You really only need to name it once, on its angular.module.

/app/core/layout.js

export default angular.module('app.layout', [])  
  .directive('lumxNavbar', require('./nav/nav'));

This way, name changes remain very flexible even between files.

Add the directive to index.html and you should be able to see our working navbar.

/app/index.html

<body>  
<lumx-navbar></lumx-navbar>  
<!-- ... -->  

Nice!

3. require(templates)

This lumxNavbar templateUrl doesn't allow us to move things around very much. And the path is already getting long: app/core/nav/nav.html.

We can simplify this with the raw-loader. Install it as a dev dependency.

npm install -D raw-loader

Add another loader to our app/webpack.config.js file.

{
    test: /\.html/,
    loader: 'raw'
}

Note: Restart the webpack-dev-server for any config changes to take effect.
And now we can require html files using relative paths, this makes it much easier to move folders around.

/app/core/nav/nav.js

/* old templateUrl: './core/nav/nav.html' */
template: require('./nav.html')  

4. require(json)

By now you're probably getting the hang of loaders. Just to be sure, let's load some json, get the json-loader.

npm install -D json-loader

Add it to the webpack.config.js.

//webpack.config.js

{
    test: /\.json/,
    loader: 'json'
}

We can put all of our main data into an index.json file, so when we make frequent navbar changes in the future, we won't have to dive into the nested /app/core/nav/nav.

/app/index.json

{
  "title": "Module Loaders",
  "version": "0.3.0",
  "links": [{
    "text": "Webpack",
    "link": "http://webpack.github.io"
  }, {
    "text": "Require.js",
    "link": "http://requirejs.org/"
  }, {
    "text": "Jspm",
    "link": "http://jspm.io/"
  }]
}

Let's require this file in nav.js

/app/core/nav/nav.js

class NavCtrl {  
  constructor() {
    this.app = require('../../index.json');
  }
}

But what if we move the nav folder around? Wouldn't an absolute path to app/index.json be more useful?

Luckily, with webpack we can use both.

5. require(absolute & || relative paths)

A relative path points to files relative to the current directory.

parent.js  
├── file.js
│   ├── folder
│   │       └──child.js
  • Parent ../parent.js
  • At the same level ./file.js
  • Nested ./folder/child.js

But if you want to move the folder or child.js around, the path will break.

Sometimes a relative path is best, but other times it's better to use an absolute path.

To use absolute paths with Webpack, we must first tell webpack.config our absolute root.

/app/webpack.config.js

module.exports = {  
  /* ... */
  resolve: {
    root: __dirname + '/app'
  }
};

Now we can point to our index.json file in a much cleaner way.
Note: Again, you'll have to restart the webpack-dev-server for any config changes to take effect.

class NavCtrl {  
  constructor() {
    /* old this.app = require('../../index.json'); */
    this.app = require('index.json');
  }
}

6. if (condition) { require('module') }

Say we want to run some angular optimizations, but only during production. Normally this would require a separate code base, but with Webpack we can nest modules within if statements.

For example, with ES6 modules, we can only import files at the top of the file. They cannot be wrapped in any blocks. Webpack's require is much more flexible.

The goal: if (mode === production) { load production optimizations }.

/app/core/config/production.js

export default (appModule) => {  
  appModule.config(($compileProvider, $httpProvider) => {
    /* less watchers from console debugging: https://docs.angularjs.org/guide/production */
    $compileProvider.debugInfoEnabled(false); 
    /* process multiple responses @ same time: https://docs.angularjs.org/api/ng/provider/$httpProvider */
    $httpProvider.useApplyAsync(true);
  });
};

Here we're loading the root appModule and providing it with some config optimizations.

Let's put in an if(){} statement to load production.js only when we are using production mode.

/app/core/bootstrap.js

require('./vendor.js')();  
var appModule = require('../index');  
if (MODE.production) { // jshint ignore:line  
  require('./config/production')(appModule);
}
angular.element(document).ready(() => {  
  angular.bootstrap(document, [appModule.name], {
    //strictDi: true
  });
});

Notice a few optimizations using MODE.production. But where does MODE come from? We can let webpack know.

/app/webpack.config.js

module.exports = {  
/* ... */
plugins: [  
    new webpack.DefinePlugin({
      MODE: {
        production: process.env.NODE_ENV === 'production'
      }
    })
  ]
}

Production mode can now be called when declare the NODE_ENV=production.

NODE_ENV=production node node_modules/.bin/webpack-dev-server --content-base app  

This method can also be used for loading angular-mocks during MODE.test, etc.

Conclusion

Webpack's require gives you a lot more flexibility for building modular apps.

But we're really only scratching the surface of what Webpack can do. Check out the docs for more.

And again, check out the codebase or post any issues on Github. If you have any suggestions or other uses, post a comment below.

]]>
<![CDATA[Webpack & Angular: Part 2]]>Part 2

Complex Webpack Dependencies

If you're unfamiliar with Webpack, you might want to checkout Part 1 of this Article on setting up a project with Webpack. This demo will continue from the previous article's code-base.

In this article we'll look at loading different types of dependencies: scripts, styles, fonts,

]]>
http://localhost:2368/webpack-angular-part-2/fdbf16ae-8929-4a47-be85-146a1cb898d1Wed, 15 Apr 2015 02:37:15 GMTPart 2

Complex Webpack Dependencies

Webpack & Angular: Part 2

If you're unfamiliar with Webpack, you might want to checkout Part 1 of this Article on setting up a project with Webpack. This demo will continue from the previous article's code-base.

In this article we'll look at loading different types of dependencies: scripts, styles, fonts, etc. using Webpack. We'll also compare and contrast loading modules from NPM & Bower.

Webpack & Angular: Part 2

LumX

LumX is a great Material Design based CSS Framework built for Angular.

I would argue LumX looks better in both style and code-style when compared to angular-material. Again, that's largely a matter of opinion.

LumX will make a good example as it comes with a lot of different types of dependencies: scripts, styles, fonts. Let's see how Webpack can combine them into a single bundle.js file.

Bower Setup

Make a bower.json file.

bower init  

Get some practice pressing enter really fast and agree to all the defaults.

Create a file called .bowerrc in the root. This will move all our downloaded bower components into the specified directory.

{
  "directory": "app/bower_components"
}

We're going to need lumx, install it.

bower install --save lumx  

We should let Angular know we're going to be using Lumx.

/app/index.js

module.exports = angular.module('app', [  
  'lumx'
]);

LumX comes with a party of dependencies. Look in app/bower_components and you'll see them all.

bower_components  
├── angular
├── bourbon            // Sass mixins
├── jquery
├── lumx                
├── mdi                // Material Design Icons
├── moment             // time
└── velocity            // jQuery animations

Bad news at this point.

Webpack Prefers NPM over Bower.

Don't worry, it'll work out.

NPM vs. Bower

It's true, Webpack can handle both CommonJS & AMD (asynchronous) modules. But Webpack has a preference: CommonJS.

Let's compare NPM and Bower for a minute.

NPM has nested dependencies, meaning that you can have different packages all loading different versions of lodash at the same time. It's very specific.

Bower, on the other hand, flattens dependencies. As such, it is often used on the front-end because, well, obviously, it isn't ideal to have 3 versions of jQuery loaded every time you visit a webpage.

Anyway, that information probably wasn't very helpful, but it's nice to know. To the point:

NPM and Bower aren't the same, and Webpack prefers NPM (CommonJS). According to the Docs:

In many cases modules from npm are better than the same module from bower. Bower mostly contain only concatenated/bundled files which are:

More difficult to handle for webpack More difficult to optimize for webpack Sometimes only useable without a module system So prefer to use the CommonJs-style module and let webpack build it. Source.

Luckily most packages have NPM & Bower equivalents, though there doesn't seem to be much interest in making LumX an NPM module. See the open issue and comment about how much you want more NPM!

Let's get emotional now and get rid of all of our Bower Lumx dependencies. If it's not NPM, it deserves a subtle level of disgust.

app/bower_components  
├── bourbon    
└── lumx

If you want to keep them from coming back, go into bower_components/lumx/bower.json and delete the dependencies. However, you'll just have to do this again if you update LumX in the future.

From here on in, we're going to try to NPM almost everything.

NPM! NPM!

Now let's NPM install the dependencies we just deleted from Bower.

                               /* NPM Package Name */
"dependencies": {               ====================
    "angular": "latest",        // angular
    "jquery": "latest",            // jquery
    "velocity": "latest",        // velocity-animate
    "moment": "latest",            // moment
    "bourbon": "latest",        // node-bourbon (not necessary)
    "mdi": "1.0.8-beta"            // mdi
  }

As you can see, there really are easy NPM equivalents. Install the dependencies.

npm install --save angular jquery velocity-animate moment mdi@1.0.8-beta  

Require(NPM_Module)

It should still work. Now let's load some primary NPM dependencies in a file we'll call vendor.js.

/app/core/vendor.js

module.exports = function () {  
    /* must be in order */
  require('jquery');
  require('velocity-animate');
  require('angular');
};

LumX seeks a few dependencies as globals, so we'll have to change this a little.

global attaches a value to the global context, likely the browser window.

/app/core/vendor.js

module.exports = function () {  
global.$ = global.jQuery = require('jquery');   // $ for Lumx, jQuery for velocity  
  require('velocity-animate');
  require('angular');
  global.moment = require('moment');            // for LumX
  };

Require(Bower_Component)

We'll have to inject some dependencies into LumX to get it to load properly. For this we need the imports-loader.

npm install -D imports-loader

Now we can require Lumx, even though it is a Bower package.

module.exports = function () {  
global.$ = global.jQuery = require('jquery');  
  require('velocity-animate');
  require('angular');
  global.moment = require('moment');
  require('imports?angular!../bower_components/lumx/dist/lumx.js');
  };

imports? tells webpack to use the imports-loader, and angular! says to inject angular into the file. You could also inject jQuery, but it's already global.

There is probably an easier to way load Bower packages, if you know how, please post in the comments. This worked for me.

Note: another possible suggestion would be to load Lumx as an NPM module using debowerify, as posted by Mallim here. I plan to explore this option later.

Require(styles)

LumX depends on a Bourbon Sass mixins which also have an NPM equivalent: node-bourbon. However, LumX requires them using a relative path within the bower_components folder, so it's better just to keep the Bower Bourbon file.

Style sheets can be loaded using require('.path/to/_lumx.scss'), as in the previous article but due to the cascading nature of stylesheets, it's likely better to keep them in a root index.scss file. Simply import the Lumx styles.

/app/index.scss

@import './bower_components/lumx/dist/scss/_lumx';

Require(Fonts & Icons)

We'll need another loader for fonts & icons. Install the file-loader.

npm install -D file-loader

Add the loader to your webpack.config file and tell it to grab anything that looks like a font.

/webpack.config.js

{
    test: /\.(woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
    loader: 'file-loader?name=res/[name].[ext]?[hash]'
}

Load up the Material Design Icons. The materialdesignicons.scss will point to our font files, which will get loaded by the file-loader.

/app/core/vendor.js

/* Styles */
  require('../index.scss');
  require('../../node_modules/mdi/scss/materialdesignicons.scss');

Create a test to see if icons and fonts are loading in index.html.

/app/index.html

<p class='fs-headline'>Icon Test: <i class="mdi mdi-twitter"></i> @Sh_McK</p>  

Conclusion

We now have our LumX dependencies running: scripts, styles, fonts & icons, oh my!

We saw how Webpack can load different file formats, as well as handle different module types (NPM or Bower). Webpack prefers NPM.

Checkout Github for the full codebase.

In Part 3 we'll finally be able to take advantage of using Webpack with Angular for creating incredibly modular code.

]]>
<![CDATA[Webpack & Angular: Part 1]]>Part 1

Getting Started

There are a lot of module loaders out there: Require.js, JSPM using System.js, to name a few.

Eventually the JavaScript community will come around and land on a winning module loader. My guess is Webpack, or something very similar.

Go with Webpack. Webpack provides

]]>
http://localhost:2368/webpack-angular-part-1/cb5538e4-e1d4-402c-ae10-d24d742fe4c6Wed, 15 Apr 2015 02:37:06 GMTPart 1

Getting Started

Webpack & Angular: Part 1

There are a lot of module loaders out there: Require.js, JSPM using System.js, to name a few.

Eventually the JavaScript community will come around and land on a winning module loader. My guess is Webpack, or something very similar.

Go with Webpack. Webpack provides an elegant and multi-featured approach to module loading. It does everything I wanted it to do, and more. Really, a lot more.

Let's try it out. We'll setup a project using Webpack, including ES6 transpiling & Sass loading. In this example, we'll setup an Angular based project using Webpack.

Webpack & Angular: Part 1

Free free to load the basic project from Github.

File Setup

File Structure:

root  
├── app
│   ├── bower_components
│   ├── core
│   │       ├──bootstrap.js
│   │       └──vendor.js
│   │
│   ├── index.html
│   ├── index.scss
│   └──index.js
├── .jshintrc
├── node_modules
└── package.json

This should be the bare minimum required to check if everything is working.

/app/index.html

<!doctype html>  
<html lang="en">  
<head>  
  <meta charset="UTF-8">
  <title>Webpack & Angular</title>
</head>  
<body>  
<p>Angular is working: {{1 + 1 === 2}}</p>  
<script src="bundle.js"></script>  
</body>  
</html>  

/app/index.js

alert('loaded!');  

Webpack

Setup

Let's create a package.json file to get started.

npm init  

Agree to whatever defaults.

We're going to need a few basic dev-dependencies to get started with webpack.

npm install -D webpack  

Webpack will also require a webpack configuration file: webpack.config.js. Make the file and add the following:

/webpack.config.js

'use strict';  
var webpack = require('webpack'),  
path = require('path');  
// PATHS
var PATHS = {  
  app: __dirname + '/app',
  bower: __dirname + '/app/bower_components'
};
module.exports = {  
    // config goes here
};

Webpack is a lot easier than it looks. You just need to provide an entry and an output.

Notice bundle.js is the only script we needed to load in our index.html. Everything will go into that bundle.

Later you can have multiple bundles for easy lazy-loading and code-splitting.

/webpack.config.js

module.exports = {  
    context: PATHS.app,
     entry: {
           app: './index.js'
    },
    output: {
        path: PATHS.app,
        filename: 'bundle.js'
    }
}

We now have a module loader.

Let's build our bundle in the terminal.

webpack  

This should create the app/bundle.js file. Check it out. It's mostly a bunch of webpack__require statements.

Webpack-Dev-Server

Webpack-dev-server is a quick and easy Node.js/Express/Socket.io app that creates your bundle.js file on the fly and reloads it on changes.

Install it as a dev-dependency.

npm install -D webpack-dev-server  

But wait, there's more!

Hot Mode

Hot mode = live-reload of modules. No need to reload the entire project on every change, just load what changed. It makes sense and it's awesome.

It's not much work either. Update your webpack.config file.

/webpack.config.js

entry: {  
    app: ['webpack/hot/dev-server', './index.js']
  }

You may want to install webpack-dev-server globally. Otherwise you'll have to run it the long way: node node_modules/.bin/webpack-dev-server --content-base app/ --hot

Run it.

npm install -g webpack-dev-server  
webpack-dev-server --content-base app/ --hot  

Open up http://localhost:8080/webpack-dev-server/.

It's hot.

/app/index.js

alert('hot-loaded!');  

It updates amazingly fast. Again, unlike Gulp or Grunt, Webpack only needs to re-compile the module that changed.

Targeted reloading might not be important to you now, but as your project grows in size & complexity it becomes increasingly useful.

Quick Start

If you're used to using Gulp or Grunt, you probably like the time saving gulp serve, grunt serve shortcuts for running your app.

This can be accomplished with package.json scripts.

/package.json

"scripts": {
    "start": "webpack-dev-server --content-base app --hot"
  }

Now run npm start. Again, the app can be found at localhost:8080/ by default, or localhost:8080/webpack-dev-server for the hot-module version.

Bootstrap Angular

I like to bootstrap Angular, rather than adding ng-app="app" into the html.

/app/core/bootstrap.js

/*jshint browser:true */
'use strict';  
// load Angular
require('angular');  
// load the main app file
var appModule = require('../index');  
// replaces ng-app="appName"
angular.element(document).ready(function () {  
  angular.bootstrap(document, [appModule.name], {
    //strictDi: true
  });
});

Notice require('angular')? That replaces adding <script src="bower_components/angular/angular.min.js">. No need for that, this is a module system.

Also note that appModule.name will be taken from index.js, whatever its name might be: angular.module('THISNAMEHERE', []).

Make the app file: index.js.

/app/index.js

module.exports = angular.module('app', []);  

Finally, let's make bootstrap.js our new Webpack entry point.

/webpack.config.js

entry: {  
    app: ['webpack/hot/dev-server', './core/bootstrap.js']
  }

Run the app (npm start). If all went well, running the app you should see: "Angular is working: true" at localhost:8080 or localhost:8080/webpack-dev-server.

Add Dependencies

Install angular.

npm install --save angular

Bootstrap will get messy if we keep loading all our dependencies in there. Let's load them in a separate file called vendor.js.

/app/core/bootstrap.js

require(./vendor')();                    // run an empty function  
var appModule = require('../index');  

/app/core/vendor.js

module.exports = function () {  
    /* JS */
    require('angular');
};

This file will get longer later.

Styles

Webpack doesn't just load JavaScript, it can load nearly anything we might need: styles, images, fonts, etc.

It handles these different file formats using loaders. Here's a list of available loaders.

Let's start with the Style, CSS, and Sass loaders and install them as dev-dependencies.

npm install -D style-loader css-loader sass-loader`  

Webpack can use a Regex test to determine which loader to use. Add this to your webpack.config.js file.

/webpack.config.js

module.exports = {  
/* context, entry, output */
 module: {
    loaders: [
      {
        test: /\.scss$/,
        loader: 'style!css!sass'
      }
    ]
  }
 };

Loaders process from right to left. Meaning that if a .scss file is required as in the example, it will follow this order: sass loader => css loader => style loader

Run a quick test with a style sheet.

/app/index.scss

body {  
    background-color: red;
}

Require the file.

/app/core/vendor.js

module.exports = {  
    /* Styles */
      require('../index.scss');
  /* JS */
  require('angular');
 }

Take a look, npm start, the background should now be red.

ES6 Loaders

Webpack makes it easy to use compiled languages like ES6, TypeScript, CoffeeScript, etc. Let's write our app in ES6 and compile it to ES5/ES3.

First we need some loaders. Install the dev-dependencies:

npm install -D jshint-loader babel-loader ng-annotate-loader

As before, we provide a loader object with a pattern matching test case. We'll exclude compiling packages.

/webpack.config.js

loaders: [  
{
    test: /\.js$/,
   loader: 'ng-annotate!babel!jshint',
   exclude: /node_modules|bower_components/
}
]

Webpack will take any required .js files, and run them right to left: jshint => babel => ng-annotate.

Let's use an ES6 example to make sure everything is working.

/app/index.js

module.exports = angular.module('app', []);  
// default params
function printMessage (status='working') {  
// let
  let message = 'ES6';                    
// template string           
  console.log(`${message} is ${status}`);    
}
printMessage();  

Run the app, npm start, and you should see "ES6 is working" in the console.

Removing JSHint Errors

You probably saw some warnings (in yellow) when you ran the app.

You might want to remove these warnings from the console caused by jshint using a .jshintrc file. You can take Jon Papa's recommended .jshintrc or add the following:

/.jshintrc

{
  "esnext": true,
  "node": true,
  "globals": {
    "angular": true,
    "console": true
  }
}

Conclusion

When I made my first webpack app, I was left wondering:

What happened to the build stage?

Where's the heavy lifting we need Grunt/Gulp for?

But it's all in the few lines of code in that webpack.config file. The app is built everytime you run webpack, and built and updated on the fly when you run the webpack-dev-server.

Everything goes in the bundle.js. It fits my criteria for a good module loader: it's simple and it works.

Granted, this was a simple use case. We'll look at how Webpack handles more complicated cases in the next post, as we setup a project requiring LumX, a popular Material Design based CSS Framework for Angular.

]]>
<![CDATA[Why JavaScript isn't Popular in Korea]]>The south. Before you ask, it's the south. I know there are no dumb questions, but yeah, it's South Korea we're talking about here.

South Korea is known for its tech industry. Samsung. LG. Samsung, again. You're likely even reading this on a Korean made computer, monitor or phone. But

]]>
http://localhost:2368/javascript-not-popular-in-korea/e26b7ee9-147d-4b17-a9ee-0d2d944d0201Wed, 11 Mar 2015 15:43:02 GMT

The south. Before you ask, it's the south. I know there are no dumb questions, but yeah, it's South Korea we're talking about here.

South Korea is known for its tech industry. Samsung. LG. Samsung, again. You're likely even reading this on a Korean made computer, monitor or phone. But where Korea excels at hardware, they fall behind on the web.

This is a country where online shopping has grown nearly ubiquitous. Online gaming has more than one 24-hour channel that people watch. A place where you file your tax return by simply clicking a few times online. And the connection is fast. Opportunity & connectivity aren't the issue.

It seems as if everyone is on a smart phone all of the time, yet few websites are responsive. C, C++ & Java are the main in Korea, JavaScript the stranger. It's as if Korea skipped the web and went directly into mobile software.

Have a look at a map of a recent AngularJS conference meetups. Notice the presence in East Asia, it's not entirely the timezone difference but largely a lack of interest.

Why JavaScript isn't Popular in Korea

So what are the reasons why JavaScript - the most common and perhaps most popular programming language - lacks much ground in Korea?

1. The Browser

What did the Korean web developer say when he was told he had to continue support for IE6? '아이이고!' That was a joke, and you know it was funny because I just told you.

OTL.

Not an acronym. That's a guy bashing his head on the ground.

Back to the browser. Browser usage in Asia can look quite different from the western world.

Pop quiz: What do these names have in common:

  • Qihoo360
  • TencentQQ
  • Sougou
  • 2345
  • Cheetah
  • UC
  • Maxthon

Answer: They are all browsers in China that are more popular than Firefox.

Good news: in Korea the big players are the ones you might be used to: IE, Chrome, Firefox, Safari.

Bad news: the big one is IE at about 70-80%. Not that IE10 or IE11 are bad, they're great. It's the older relatives that make the developers & designers OTL. In fact, some JavaScript frameworks such as AngularJS 1.3 have already dropped IE8 testing support, leaving about 20% of Korean users out of luck.

Why IE? Whyyyyyyy???

The IE 'stranglehold' goes back to a 1999 Internet security law that guarantees that all online shopping must be done with IE. No joke. You still have to use ActiveX.. In 2015. For web security.

In other words, someone using a macbook running OSX can't buy anything online. Even with the big players, gmarket.co.kr, owned by eBay, I can't buy anything on there without using an out-of-country credit card. Many major government, education and corporate websites just don't even work without IE.

The IE situation has lead to an interesting situation: the normalization of website tech support. I once had someone help me with my online banking, which led to a 30 minute phone call with the sites tech support, trying to fix Windows, ActiveX & IE issues. Though the whole operation seemed shocking to me, it was treated as shockingly normal.

2. The Geography

The geography of Korea helps explain a lot about why client-side frameworks aren't popular.

First of all, you're never offline. High speed Internet still works on your phone when you're on the subway. Deep underground. Going through a mountain.

Secondly, as in any major city, you're never far from a server. Yes, the country of Korea largely approximates the size and population density of a city.

These two factors combined indicate server-side transfer speeds and connectivity are enough. Korean developers don't have to worry as much about users clicking on a button and nothing happening as they rarely face slow or dropped connections.

3. The Job

Developer sounds like a great job. But not in Korea. Korean coders are largely over-worked, underpaid, and vastly under-appreciated. Many tech company offices look like the movie Office Space.

As a result, there is a computer science brain drain in Korea where one of the main limiting factors is English fluency. It's hard to keep the best developers when heading overseas may reduce your work hours and double your salary. Rarely does picking up a second language pay so well.

The language barrier also doubles as an impediment to learning new skills. Imagine how hard it would be if you had to learn Korean in order to study and keep up with the fast changing JavaScript world. Grunt / Gulp / Backbone / Ember / Angular / CSS / Sass / LESS / Compass / Stylus / React / Functional / Isomorphic / Reactive / Traceur / Babel / NPM / Bower / JSPM / EcmaScript2015 /OTL. It's overwhelming enough as it is. This is akin to the situation Korean developers face, while working longer hours with fewer incentives. My sympathies.

Take away the light at the end of the tunnel, and coding and learning become a burden. It's no longer something you study on weekends for fun, hacking away on some dumb project for curiousities sake.

Final Thoughts

JavaScript and the web have a bright future. I hope that light shines on Korea. If you're interested in promoting AngularJS in Korea, I've started a meetup group you should join.

Why JavaScript isn't Popular in Korea

Now I could be wrong, and often am. There's nothing worse than an outsiders perspective on an insiders world, and having said that I am now officially immune to criticism. That's how the world works. If you have any corrections, let me know in the comments.

]]>
<![CDATA[Comparing Angular 1.x & 2.0]]>The Obsorne Effect

The Angular team faces a problem. How do you talk the great new features of Angular 2.0 under development without damaging use of the current 1.x? This effect is often called the Obsborne effect, named after a 1980s computer company whose marketing contributed to putting

]]>
http://localhost:2368/comparing-angular-1-x-2-0/7b73ab8b-e49c-4490-837e-9c58612201fbTue, 17 Feb 2015 03:50:27 GMTThe Obsorne Effect

The Angular team faces a problem. How do you talk the great new features of Angular 2.0 under development without damaging use of the current 1.x? This effect is often called the Obsborne effect, named after a 1980s computer company whose marketing contributed to putting the company out of business. In short, the better 2.0 sounds, the less people will want to start or continue projects built with 1.x.

But the secrets out. Angular 2.0 is available on github and you can play around with it using npm install angular@2.0.0-alpha.6. Keep in mind, it is NOT ready for production and subject to (likely a lot of) change.

Angular 1.x vs. 2.0

It's important to see why the Angular team are making such drastic changes. Angular isn't just trying to keep up, they're pushing forward a lot of standards, enhancements and better app architecture.

The more you look at the elegance of 2.0, the more 1.x looks like a bunch of hacks strewn together and prefixed with 'ng-'. While 1.x was all about adding features and getting stuff done, 2.x should have a simpler API while simultaneously targeting performance & web standards.


2-way data binding

2.0: 1-way data binding

In larger apps, 2-way binding can develop into spaghetti. Angular 2.0 will use a concept called Directed Acyclic Graph, a kind of unidirectional architecture.

This sounds a lot like what React is doing right with Flux. This kind of architecture can be used with Angular as well. Read more.

Though 2-way binding will disappear, Misko has stated that Angular 2.0 may function in a way that data bindings appear 2-way, though behind the scenes data flows 1-way.


watchers

2.0: Zone.js

$scope.$watch, $scope.$apply, $timeout. No more. Whew! Using these was part of the reason Angular 1.x had such a huge learning curve.

Zone.js helps Angular to do change detection automatically. This sounds similar to React's reconciliation diffing algorithm.

The Angular team explained change detection is now faster, uses less memory and less power. Change detection may improve further with object.observe coming to other browsers (currently just Chrome).

Zone.js also supports using immutable objects for even faster processing. This is because the compiler can assume the data objects won't change and optimize.

[edit March 11, 2015] For a more indepth look at how change detection will work in Angular 2.0 watch Change Detection Reinvented by Victor Sakvin @ngConf.


component communication

2.0: Instead of $broadcast & $emit, 2.0 has a few differences: 1) You can emit messages in the DOM, rather than the scope.
2) You can put components inside eachother and link them directly. This may be similar to components using isolate scope now.


DOM

2.0: In many ways, Angular 2.0 seems to handle DOM style manipulation with something similar to React.js's virtual DOM, which they referred to in a recent presentation as the "view". In response to a recent question about 'Angular Native?', Misko mentioned that this View could be run on a web worker or even potentially on native.


scope

Data will be organized in a tree like architecture.

Angular 2.0 will also use Web Components standards. For example, the shadow DOM could be used to create an isolate scope. The Angular team explained that there is also a shadow DOM emulated mode (for browsers not support web component features yet.) This would allow additional options for isolating css styles as well. Cool!


Modules

2.0: 2.0 is of course going to use ES6 module syntax. On top of that, Angular 2.0 is expected to have 'amazing' dependency injection with lazy-loading. Rather than using singletons, 2.0 will have a kind of hierchical data structure likely offers inheritance features. You will also be able to control the lifetime of modules such as services.


Directives

[edit March 11, 2015]

2.0: Now called "Components" Still called directives. In Angular 1.x, directives are available everywhere on instantiation, creating name-space overlap problems for large projects. In 2.0, you must import your directives which avoids this problem.

Although I'm not clear on how it works, Angular 2.0 will create a prototypical template of all potential bindings to optimize for compiler speed.

There are currently three types of directives:

  • Component Directive - Made up of a view & controller. What we might recognize as a .directive style directive.

  • Decorator Directive - adds behavior to a directive. Similar to the ng-directive attributes you add, like ng-click or ng-show.

  • Viewport Directive - handles html transformations as in ng-if or ng-repeat.


Router

2.0: Check it out: 2.0 router. It should be back-ported to 1.x as well, though without the feature of lazy-loading which was deemed unstable for 1.x.

[edit: March 8, 2015]

Brian Ford gave a presentation about the new router @ng-conf that's worth a watch. In it he describes how the new router can use both Angular 1.x & 2.x modules, allowing teams to gradually change from one router to the other. He also proposed a possible migration path from the popular ui-router.

Ui-router is great, but lacks some important features. For example, resolve can only pass data before a page is loaded. What if you want to check if a users current data is saved in a form before routing to the next page? Ui-router's resolve is a one-time trigger. Instead, the new router will provide 'Lifecycle Hooks' that let you specify exactly when you want an action to take place.

Component directives can be routed to using the new-angular-router. If this sounds crazy to you, you can already do something similar in angular 1.x by dropping controllers for directives and routing to a template. Check out this example for inspiration.


HTML

2.0: Though the syntax looks very different, keep in mind that the differences have good reasons behind them.

ng-directives

Components in the HTML are broken up into two types: (events) & [properties]. They are wrapped in round or square brackets to help both humans and the computer differentiate and optimize for the two types.


(events)

(events) refer to user initiated actions.

1.x 2.0
ng-click (click) (dbl-click)
ng-keyup (keyup)

[properties]

[properties] now link directly into the DOM properties.

1.x 2.0
ng-hide [class:hidden]
ng-checked [checked]

*foreach

!foreach is the proposed replacement for ng-repeat.

<ul>  
<li *foreach="#item in itemService.items"></li>  
</ul>  

#item

Items prefixed with a # can bind directly in the html. No more ng-model.

<input type="text" #userName />  

{{ }}

Double curlys are still in 2.0. See! Not everything will change.


directive names

No more camelCase & snake-case confusion. Now you specify the directive name in the component. Assuming Angular 2.0 follows web component standards, it will require a '-' in the name.

@Component {
    selector: 'myApp-component'
}

Final Thoughts

Angular 2.0 looks fantastic. It's not ready yet, but you can play around with it today. Checkout the github for more. There are also some examples available, such as ng2do.

[edit March 11, 2015] Definitely catch the keynotes from ng-conf 1 & 2 as well as the fresh faced new angular.io site.

If you're looking to prepare for the learning curve, there are a few things you can do now.

  • Try out Rob Eisenbergs new framework: Aurelia. It's definitely worth a look.
  • Learn more about web components and shadow DOM.
  • Use ES6 - (now ES2015?) - with Angular 1.x. There's a great example using ES6 & JSPM here.
  • Learn more about Facebook's React.js. A lot of great concepts are stemming from the great work there, including Flux.

At a glance, Angular 1 & 2 have very little in common. 2.0 looks more like a complete overhaul than an episode of Pimp my Framework. So with the learning curve for 1.x, why continue sinking time into a framework that may quickly become vaporware?

[edit March 11, 2015]

Recently, I've had this questioned answered. Seeing that 1.x & 2.x apps can work together with the new router is a strong case towards continuing with Angular 1. I also now see efforts towards a migration path, as well as a lot of similarities in code style.

Embracing change can be a good thing, but you have to do it at the right time. Too early, and your efforts may outweigh the benefits. Too late, and you're, well... you're too late. For now, I remain enthusiastic about 1.x, and for that I thank the fantastic Angular community.

]]>
<![CDATA[ES6 Generators with Angular]]>ES6 Generators

With Christmas come early this coming June, JavaScript is getting a shiny new coat of paint. ES6 comes with a lot of great new features. In particular, if you haven't tried generators yet, or if you have, and they still don't make sense, this post might be helpful.

]]>
http://localhost:2368/es6-generators/5334cc68-20d3-47b5-be59-158406a6474aFri, 13 Feb 2015 05:31:34 GMTES6 Generators ES6 Generators with Angular

With Christmas come early this coming June, JavaScript is getting a shiny new coat of paint. ES6 comes with a lot of great new features. In particular, if you haven't tried generators yet, or if you have, and they still don't make sense, this post might be helpful.

ES6 (node-harmony, iojs) with generators are already common in Node.js. Checkout Koa.js by the original creators of Express. So why don't we see them much on the client-side? The client-side environment is harder to control, but with transpilation we can avoid this problem.

ES6 Setup

In order to get started with ES6 today, you're going to need to change your JavaScript into standard ES5 code. This is called transpilation. If you plan on supporting older browsers in the future, you might as well get used to the process, as its a great way to use ES6 & proposed ES7 features today.

You can get started with ES6 in the browser today using a real-time compiler such as Traceur or the pre-compiler Babel (formerly named 6to5). Or if generators are the only thing you're looking to add to your code, Facebook has a project called Regenerator.

An easy way to get started is to use the Yeoman generator gulp-angular. It provides options for a setup for either Traceur or 6to5. Unfortunately, I'm still looking for a better quick-start option for handling modules, perhaps with JSPM (ideas?).

Human Readable Async

Generators can help make your async code look human readable again. Let's compare traditional callback methods with generators. Spoiler alert: generators are way better.

Callbacks

function callbackFunction (var1) {  
    first(success, failure) {
        if (success) {
            getSecondDependency(var1, success, failure) {
            if (success {
                second(secondDependency, success, failure) {
                if (success) {
                    third(success, failure) {}
                    fourth(sucess, failure) {}
                 }}}}}}}
  • Plus one for side scrollability.

And the contender: Generators with spawn().

ES6 Generators with Spawn

function generatorWithSpawn (var1) {  
   spawn(function* () {
    try {
      yield first();
      var secondDependency = yield getData(var1);
      yield Promise.all(
        second(secondDependency),
        third(),
        fourth()
      );
   }
   catch (error) {
       console.error(error);
   }
   });
});
  • Plus one for readability.
  • Plus one for error handling.
  • Plus one for easy modification.

How Generators & Spawn Work

spawn() simply wraps around your generator function* and runs the generator until it is complete.

Whenever a process is async, you yield to it. Yield acts like a callback, saying 'pause here until the data comes back.'

Spawn calls the next() iterator when every yield is complete until finished. Use a try & catch blocks for better error handling.

Rather than $q, you can use Promise, another es6 feature to handle calls. There's a better example of using Promises and Spawn here.

Keep in mind that spawn functions are intended to return anything so there's no need to return anything. The spawn() function simply returns undefined.

Setup Spawn in Angular

Adding spawn as a service in Angular is pretty simple. This service is basically just taken from Jake Archibalds blog post here. and tossed into Angular.

/* ES6 Generator - Spawn 
 * Thanks to http://jakearchibald.com/2014/es7-async-functions/ */
(function () {
  'use strict';
  angular.module('angularEs6Spawn', [])
    .factory('spawn', spawn);
function spawn() {  
    return function (generatorFunc) {
      function continuer(verb, arg) {
        var result;
        try {
          result = generator[verb](arg);
        } catch (err) {
          return Promise.reject(err);
        }
        if (result.done) {
          return result.value;
        } else {
          return Promise.resolve(result.value).then(onFulfilled, onRejected);
        }
      }
      var generator = generatorFunc.apply(this, arguments);
      var onFulfilled = continuer.bind(continuer, "next");
      var onRejected = continuer.bind(continuer, "throw");
      return onFulfilled();
    };
  }

Drop that code in and add the dependency 'angularEs6Generator` to your app.

Follow-up

Generators are great. Read more about what you can do:

  • next() can be called with a value passed to the yield statement. For example:
next(function(a) { return a + 1; }  

This is potentially quite valuable. Check out an example here.

  • CSP - check out the ping pong game example.

Read More

It's even easier than it looks. Read more about ES6 Generators:

]]>