Check out our new training course on AngularJS for Flex Developers

Open a Link in a New Window with AngularJS - Approach 1

I was working on a client project, built with AngularJS, and we wanted to open another application in a new window. This is a simple, common task, that you can accomplish with an href and a target. But we wanted to look for the most Angular way to accomplish it. Triggering the link in Angular gave us the option to do logging, or other functionality, before the click occurs. I decided to write a series about the different ways to make this happen.

The Setup

First, add Angular to your Application:


<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>

Then, create an Angular Module and controller:


angular.module('test',[]);
angular.module('test').controller('someController',['$scope','$window', function($scope,$window){
}]);

Two elements are injected into the controller. $scope is the common service used to communicate between the view and the controller. $window gives you an Angular reference to the browser's window object. We'll use $window to open the new page.

Open the new page

This method will open a new page:


$scope.onButtonClick = function(){
$window.open('http://www.jeffryhouser.com');
}

A function named onButtonClick() is saved to the $scope. Inside the button, the $window.open() method is called. This will force the window to open the URL in a new window.

Now add some HTML:


<body ng-app="test">

<div ng-controller="someController">
<button ng-click="onButtonClick()" >Open Link Standard</button>
</div>

The ngApp tag is put on the body. The ngController is put on a div. A button inside the div uses ngClick to call the onButtonClick() method.

Load the app and you'll see something like this:

A boring UI; but click the button:

The link to my blog will open in a new tab, based on my default browser settings.

Play with the code here.

What is Next?

The next entry in this series will show you how to use a similar approach to submit a form into a new window. Then, I'll write an entry about holding off on opening the new window until after an asynchronous call is complete. The last part is where things start to get complicated; but bear with me. We'll get there quickly.

Building Angular 2 TypeScript Applications with Gulp and Browserify

I've been dealing a lot with build processes and build scripts lately. This blog post will show you how to build Angular 2 applications with Gulp discuss some of the limitations I found with the approach.

When reading the TypeScript docs, Browserify is the tool of choice for compiling TypeScript with Gulp. I wanted to see if I could get it working when dealing with Angular applications.

For the purposes of this post; I'm not going to review a TypeScript / Angular 2 application; I'm just going to use a simple Hello World from the Angular 2 docs.

The Setup

First, you'll need to install the required nodeJS Dependencies. Instead of installing everything independently, just copy this into a package.json file:


{
"name": "Angular2TypeScriptGulpBrowserifySample",
"version": "0.0.1",
"description": "DotComIt Project Sample for building Angular 2 Apps with TypeScript, Browserify, and Gulp.",
"author": "Jeffry Houser",
"license": "ISC",
"dependencies": {
"@angular/common": "~2.4.0",
"@angular/compiler": "~2.4.0",
"@angular/core": "~2.4.0",
"@angular/forms": "~2.4.0",
"@angular/http": "~2.4.0",
"@angular/platform-browser": "~2.4.0",
"@angular/platform-browser-dynamic": "~2.4.0",
"@angular/router": "~3.4.0",
"angular-in-memory-web-api": "~0.2.2",
"systemjs": "0.19.40",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.8",
"rxjs": "5.0.1",
"zone.js": "^0.7.4"
},
"devDependencies": {
"browserify": "^13.3.0",
"gulp": "^3.9.1",
"tsify": "^3.0.0",
"typescript": "^2.1.4",
"vinyl-source-stream": "^1.1.0"
},
"repository": {}
}

Run this command:


npm install

To install everything. The dependencies are all the relevant Angular 2 Modules. The devDependencies are all the node projects used in the gulp script:

  • Browserify: Browserify is a tool for concatenating JavaScript files into a single one.
  • Gulp: Gulp is our script runner tool.
  • tsify: A Browserify plugin to compile TypeScript files
  • TypeScript: The module used for compiling TypeScript.
  • Vinyl-Source-Stream: Vinyl is the format used by Gulp. This task will convert Browserify output into something Gulp can use.

With everything installed, we are ready to start writing our Gulp Scripts.

TypeScript Configuration

We'll want to configure the TypeScript compiler to make things work. Just create a file called tsconfig.json in the application's root directory:


{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [ "es2015", "dom" ],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
}
}

I'm not going to expand on the details of this for the purposes of this sample. I think I borrowed it from one of the samples on the TypeScript web site.

The Gulp Script

Start with an empty Gulp Script, named gulpfile.js, and import the required libraries:


var gulp = require("gulp");
var browserify = require("browserify");
var source = require('vinyl-source-stream');
var tsify = require("tsify");

Now, create a few variables. First, the source root:


var sourceRoot = "src/";

For all my projects, I put the source in a directory named src. Also, define the final minimized JavaScript file:


var javaScriptDestinationFile = 'app.min.js';

I named it app.min.js, but you can change it if you need to.

Define the final destination path:


var destinationPath = 'build';

I always build my projects into a directory named build.

Finally, we are going to define something called the entry. This is the first TypeScript file that defines the application. All other TypeScript files will be referenced from the initial application entry point:

var appEntries = [sourceRoot + 'main.ts']

The file is named main.ts.

Let's create the gulp task:


gulp.task("buildTS", function () {

}

I named the task buildTS, for Build Type Script. This is a common convention I use with a lot of project setups. Right now the task does nothing, let's add in browserify:


return browserify({
entries: appEntries
})

The Browserify task specifies the appEntry, but has no other properties in its configuration object.

By default Browserify does not handle TypeScript. That is what we use the tsify plugin for. The dot notation is used to chain other commands off the browserify object, so let's add in the plugin:


.plugin(tsify)

The plugin will know to look for the tsconfig.json file for configuration options. That is all that is needed for Browserify to support TypeScript code.

Next, create a bundle:


.bundle()

This is the browserify command to run the script and return the processed files. We need to turn that browserify return object into a Vinyl stream:


.pipe(source(javaScriptDestinationFile))

Thankfully we had a NodeJS plugin just for that. Next, specify the final destination of the file:


.pipe(gulp.dest(destinationPath));

This successfully creates the final file.

Run the task, like this:


gulp buildTS

You'll see some results like this:

Look in your application's directory and you should see a build directory like this:

Don't forget to copy the JavaScript and HTML libraries.

Even though Angular is primarily a TypeScript framework, it does rely on a few JavaScript libraries to run in the browser. We want to copy those from our node_modules directory to the build directory. This gulp script will do that:


var htmlSource = [sourceRoot + '**/*.html'];
var destinationPathForLibraries = destinationPath + '/js';
gulp.task('copyJSLibraries', function () {
gulp.src(htmlSource)
.pipe(gulp.dest(destinationPath));
gulp.src(['node_modules/core-js/client/shim.min.js'])
.pipe(gulp.dest(destinationPathForJSLibraries + '/core-js/client'));
gulp.src(['node_modules/zone.js/dist/zone.js'])
.pipe(gulp.dest(destinationPathForJSLibraries + '/zone.js/dist'));
gulp.src(['node_modules/reflect-metadata/Reflect.js'])
.pipe(gulp.dest(destinationPathForJSLibraries + '/reflect-metadata'));

});

I made it simple and it copies the three JavaScript files required by AngularJS in the browser: shim; zone; and reflect. An explanation of these libraries is beyond the scope of this article. This script also copies the HTML files from the src directory to the build directory.

Run the script:


gulp copyLibraries

You should see simple results like this:

Check the build directory to see the final files.

The hello world should run now. That's awesome.

What's Wrong Here?

I didn't cover it here; we this approach does allow us to generate source maps and run the final JS code through a minimizer. However, I stopped moving down this path because the generated JS file includes all the Angular libraries. That made it very big. I tried some experimentation, but could not get the application working when separating the Angular framework libraries from the custom application code.

I made the decision that the inability to separate the framework from my custom code was a deal breaker and abandoned this approach.

Final Thoughts

Since I gave up on this approach, what comes next? I'll be writing more about that in the coming weeks. Instead of using Browserify and tsify, I started using a Gulp TypeScript library directly to build the applications. This gave me the flexibility I needed to separate Angular and my custom code.

Compile Code on the Fly - TypeScript and Gulp - Part 2

This is the second in a series of articles no compiling TypeScript applications with Gulp. Check out Part 1 which covers most of the setup; or sign up below to get our fully detailed white paper.

Gulp allows us to automatically run a gulp task when a certain directory changes. This is built in and we don't need an additional plugin to make it happen. We're going to make a task which will watch for TypeScript files for changes, and then trigger the buildTS task again.

First, let's create a variable to point at the TypeScript source:


var typeScriptSource = [sourceRoot + "/**/*.ts"];

The sourceRoot variable was created in the previous article, and points to the src directory. The wild cards tell Gulp to look at all subdirectories inside the sourceRoot folder.

Now create a gulp task called buildWatch:


gulp.task('buildWatch', ['buildTS'], function(){
});

You'll notice that there are three arguments to this gulp task, something we hadn't seen before. The first is the task name, buildWatch. The second is an array of strings with each string represents a gulp task. These tasks will run before the third argument's function is executed. Here we are only running one task, buildTS, before starting the buildWatch task.

Here is the function code:


gulp.watch(typeScriptSource,['buildTS']).on('change', function(event){
console.log('Event Type' + event.type);
console.log('File Path' + event.path);
})

We use the watch() function on the Gulp object. It accepts two arguments. The first argument is a source array, in this case the typeScriptSource value. The second argument is a task array. In this case just the buildTS task. Reading this in English, it says watch for files that match typeScriptSource, and when something changes run the buildTS task. Dot notation is used to daisy chain an 'on' method to the watch. When the change event occurs, the type of event and modified files are output to the console.

Run this script:


gulp buildWatch

You'll see something like this:

The important thing to notice is that the console does not go back to a command prompt; the code is left running in the background. Change some code to see what happens:

As you save files, the script automatically notices, and reruns the appropriate task. You'll get console information about the file that has changed.

Overall, I find the watch task to be a very powerful development tool.

Yes, I want to get your white paper on building TypeScript applications

Building HTML5 Applications with TypeScript and Gulp - Part 1

TypeScript is a newish language for application development on the web. It is a superset of JavaScript, and supports things like static typing and class based object oriented programming. Static typing, particularly, can offer improved tooling over what is currently available for simple JavaScript programming.

TypeScript can be used for any web application, or even on the server side with NodeJS. It is the recommended language for Angular 2 applications. TypeScript is compiled to regular JavaScript for deployment and testing. This white paper will explain the infrastructure we use to make this happen.

The TypeScript Application

Before we start to look at the build process, let's look at a super simple TypeScript application. We'll need some code to compile. This code borrows heavily from the official TypeScript tutorials. It will add a 'hello world' message to the body of an HTML page.

Create a directory for this setup. The final directory setup will look something like this:

This is a description of each directory:

  • TypeScriptAndGulp_Article: The root directory will contain the script files for running Gulp and config file for NodeJS.
    • build: This directory will contain the final, processed, build.
    • node_modules: This directory will contain the NodeJS package, such as Gulp and TypeScript, to needed to perform the actions.
    • src: This directory will contain the application's source files.

We will create most of these files and directories as we move through the process.

For now, I named the project directory TypeScriptAndGulp_Article. Start by creating the src directory. I always separate the source code, compiled code, build scripts, and NodeJS modules. Inside the src directory, create an index.html file:


<html>
<head>
<title>TypeScript Sample for DotComIt Article</title>
</head>
<body>
<script src="sample.min.js"></script>
</body>
</html>

This is a simple index.html file. There is one item I want to draw attention to. The script tag which imports a JavaScript file named sample.min.js. This is the file we will generate from the TypeScript code.

Next, create a file named greeter.ts. The ts extension is the standard extension for TypeScript files, similar to how 'js' is the standard extension for JavaScript files. For this sample I'll put all the files inside the root of the src directory, however in a more complex application, I may categorize the files under a descriptive directory structure.

This is the greeter.ts:


export function sayHello(name: string) {
return `Hello from ${name}`;
}

This file exports a function named sayHello(). The export is not something you'll commonly see in browser JavaScript, but is used when creating NodeJS Modules. It, basically, says that "This is an API I Want people to use to access code in this file." The sayHello() method has a single parameter, name. The type of the name is specified, something that doesn't happen in JavaScript but adding it allows for type checking at the compiler level. The body of the method returns a string, referencing the name variable inside the string. The syntax is very similar to JavaScript, so learning TypeScript should not be a big hurdle for you to climb.

Now create a file named main.ts. This is the entry point to our application. Back in my school days we'd call the routine that ran the app a main routine, so this is a similar approach. The first thing the main.ts does is import the greeter file:


import { sayHello } from "./greeter";

This makes all the code from the greeter.ts file available to use in the main.ts file. Now, create a showHello() method:


function showHello(name: string) {
document.body.innerHTML = sayHello(name);
}

This method looks a lot like a JavaScript method definition, the only difference is that the name variable is given a type of string. The code accesses the innerHTML of the web pages body tags and outputs the results of the sayHello method, which will just be a string that says hello from the given name.

Finally, call the showHello() method:


showHello("World");

That completes the super simple TypeScript application. I could write a lot about TypeScript, however I wanted this article to focus on the build process of turning TypeScript into a JavaScript web application. As such, I'll leave the JavaScript there. When you finally compile the application, it should look something like this in the browser:

A Basic Compile Script

To compile TypeScript into JavaScript we are going to use NodeJS and a bunch of plugins.

Install and Setup NodeJS

The first step is to install NodeJS if you haven't already. The formal instructions will give you more detailed instructions if you haven't already done so. Then create a generic package.json configuration file. You can run this script:


npm init

And follow the instructions to create a simple package.json. You'll see something like this:

My final package.json is listed below:


{
"name": "typescriptandgulp",
"version": "1.0.0",
"description": "A sample project to compile TypeScript with Gulp",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jeffry Houser",
"license": "ISC",
"repository": {}
}

Install Node Modules

Now we want to install some NodeJS plugins. First, we want to make sure Gulp is available. Gulp is the script runner we'll use to execute tasks to run our application. Run this command:


npm install --save-dev gulp

You'll see a screen similar to this:

You can ignore the warnings. Your project directory will now have a node_modules directory.

Next, install the TypeScript plugin:


npm install --save-dev typescript

The NodeJS TypeScript plugin will not be used directly in the gulp script, but is a required dependency:

Next, install browserify. Browserify will combine all the JavaScript files into a single file. We also want tsify installed, a plugin that will allow browserify to compile TypeScript into JavaScript. First, install browserify:


npm install --save-dev browserify

You'll see results like this:

Then install tsify:


npm install --save-dev tsify

Your screen should look like this:

A Gulp stream object is named vinyl and is a virtual file format. To manipulate the output from Browserify with a Gulp script , we'll need to convert Browserify's object to the vinyl format. Thankfully there is a plugin for that, vinyl-source-stream module:


npm install --save-dev vinyl-source-stream

See the console results:

It is a lot of setup, but we should have all the required plugins we need to get started now.

Create the Gulp Task

In the root directory of the project, create a file named gulpfile.js. It is the default Gulp configuration file.

First, load the gulp module:


var gulp = require("gulp");

From there, you can create a gulp task for compiling TypeScript:


gulp.task("buildTS", function () {
});

This is a blank task that does nothing. It calls the task() method on the gulp object. The task() method has two argument: the name of the task and a function to perform the task. You can execute this task by typing this into your console:


gulp buildTS

You should see something like this:

The task does nothing yet, though. Let's make it do something. Import the rest of the libraries:


var browserify = require("browserify");
var source = require('vinyl-source-stream');
var tsify = require("tsify");

Make sure these libraries are imported outside of the Gulp task. After the library import, still outside the Gulp task, let's define a few variables. The first is something I call appEntry:


var appEntries = ['src/main.ts']

It is an array that contains the main TypeScript file. Browserify will analyze main.ts to find all other files it uses and will do recursively. This is a bit different than the process I used in an AngularJS JavaScript application; where I'd process all files ending with the js extension.

Next, create a variable for the processed file name, and one for the final path:


var javaScriptDestinationFile = 'sample.min.js';
var destinationPath = 'build';

The destination file is the final output after the TypeScript files are merged and compiled into a single one. We referenced this file name in the index.html document. The second variable specifies the final destination of the file. I could define these as part of the Gulp task, but prefer to define them as global variables so they are easily accessible across multiple tasks, and I can tweak how everything works just by changing the config values. Now go back inside the buildTS task and call the browserify() method:


return browserify({
compilerOptions: {
module: "commonjs",
target: "es5",
},
entries: appEntries
})

This calls the browserify() method and passes in an argument. The argument object specifies the configuration for this browserify process. Let's go through them:

  • compilerOptions: This is another object that specifies how the TypeScript compiler will work.
    • module: Specifies how modules are loaded in UI code, in this case we are using the commonjs convention.
    • target: Specifies the ECMAScript version you want to output to; in this case I am specifying EcmaScript 5, however other versions are supported.
  • entries: Specifies an array of entry points to your application.

This is a very simple config, and it can be a lot more complicated if you need it to be. Next, tell Browserify to compile the TypeScript code:


.plugin(tsify)

Each successive command is daisy chained on the other with the dot syntax. This uses the Browserify plugin() method to call the tsify package to compile the TypeScript code into JavaScript.

Next, call bundle() to merge all code into a single unit:


.bundle()

This one is simple. Then, specify the name of the new file:


.pipe(source(javaScriptDestinationFile))

This uses the vinyl-source-stream module to turn the javaScriptDestinationFile name into something that can be accessed via Gulp. The pipe() method means that we are getting ready to output information, instead of processing input. Finally, specify the destination of the new file:


.pipe(gulp.dest(destinationPath));

This uses the pipe() operator too; and the value is Gulp's dest() function. This, basically, tells the script to put all our files in the build directory.

You can run the gulp script:

Look at the directory structure after our first run:

All the node modules we installed are in the node_modules directory. The source we looked at earlier is in the src directory. The JavaScript file built from the TypeScript files is in the build directory. The gulpfile.js and package.json are in the root application directory. I like this structure because it cleanly separates concerns.

Things are not yet runnable in a browser, because the Index.html was not moved from the src directory to the build directory. For the sake of this article, you can move it manually. Runt he code in the browser, and you should see this:

This isn't an interesting app, but it does prove that Gulp is successfully compiling TypeScript and copying the HTML files from the source directory into the build directory.

What's Next?

The next article in this blog series will focus on how to write a Gulp Script that will watch for any changes to your TypeScript files, and re-compile them as you change code.

If you want a more in depth tutorial, sign up to get our full 30 page white paper on building TypeScript applications with Gulp.

Yes, I want to get your white paper on building TypeScript applications

@types/node is not found in the npm registry

I'm trying to run through the Angular 2 Quickstart with TypeScript.

When I try to run the npm install command I am getting a ton of errors like this:


npm ERR! 404 Not Found
npm ERR! 404
npm ERR! 404 '@types/node' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it
npm ERR! 404 It was specified as a dependency of 'angular-quickstart'
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, or http url, or git url.

npm ERR! System Windows_NT 6.2.9200
npm ERR! command "C:\\Program Files\\nodejs\\\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install"
npm ERR! cwd C:\quickstart
npm ERR! node -v v0.10.29
npm ERR! npm -v 1.4.14
npm ERR! code E404
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! C:\quickstart\npm-debug.log
npm ERR! not ok code 0

It is very frustrating to jump into something new only to find their quick start documentation does not work.

The solution appears to be to update NodeJS and npm.

I downloaded a new version of NodeJS from the NodeJS.org web site. After it was installed, you can update npm like this:


npm install npm@latest -g

Check your versioning like this:


node -v
npm -v

This upgrade appears to have solved my issues.

Select a Color -- Build a Color Picker in Angular 2 - Part 3

This section will show you how to run Angular code when the canvas is clicked on. Then it will process the image inside the canvas to determine the color and display the results out to the user. It will display results in two different ways; the first is to output the RGB values of the image. The second will be to display another canvas which is colored based on what we selected.

Modify the External Template

Open up the external template, canvas.html. We'll make a few changes here. First, add a cross hair cursor to the canvas using CSS. This will let people know the canvas can be clicked on:


style="border:1px solid #d3d3d3;cursor: crosshair;"

This might be better put in an external CSS file, but for simplicity I defined all styles in-line. The canvas will need to do something when the image is clicked, so add a click event:


(click)="pickColor($event)"

We'll create the pickColor() method inside our main app's component in the next section. Notice the click event is passed to the pickColor() method.

Now, create a section to output the selected color:


<h1>Selected Color</h1>
RGBA: {{RGBA}}<br/><br/>
<canvas id="selectedColorCanvas" width="250" height="250" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>

The first thing it does is output a variable named RGBA. This includes the red, green, blue, and alpha values that make up the selected the color. We'll create that variable in the pickColor() event method.

The second element in the template is a new canvas. This will do nothing but display the selected color of the canvas.

Modify the Script

Now move to the JavaScript code. All this code will modify the colorpicker-app component. First, we need a hook to get access to the selectedColorCanvas. Modify the queries property of the component:


queries : {
imageCanvas : new ng.core.ViewChild('imageCanvas'),
selectedColorCanvas : new ng.core.ViewChild('selectedColorCanvas')
}

The imageCanvas was there from previous samples, but the selectedColorCanvas uses the same approach. The selectedColorCanvas variable will be accessible inside the class constructor.

Inside the class constructor, create a variable for the selectedColorCanvas context:


var selectedColorCanvasContext;

Inside the image onload() method, inside the onInit() method, save the selectedColorCanvas 2D context:


selectedColorCanvasContext = selectedColorCanvas.getContext('2d');

Also, create a variable to include the RGBA value:


this.RGBA = ''

This variable is put in the 'this' scope. This is similar to the $scope of an AngularJS 1 application, and using 'this' allows the value to be accessed inside the view template.

Now, implement the pickColor() method. Here is the stub:


this.pickColor = function(event){
}

The event is passed in so we can get the x and y position that was clicked on the image:


var data = imageCanvasContext.getImageData(event.layerX, event.layerY, 1, 1).data;

This loads all the image data using the getImageData() method on the imageCanvasContext. The values into this method are the x value, the y value, the width, and height. layerX and layerY values from the event object specify the location that was clicked. By specifying 1, 1, for the width and height we get all the information for the single pixel which was clicked.

The data object contains an array with four elements, representing the red, green, blue, and alpha properties on the pixel that was clicked. Now, let's draw that color on the selectedColorCanvas:


selectedColorCanvasContext.fillStyle = "rgba(" + data[0] + "," + data[1] + "," + data[2] + "," + data[3] + ")"
selectedColorCanvasContext.fillRect(0,0,250,250);

First the fillStyle is defined, as a string, using the rgba() method along with the RGBA data. Then the fullRect() is called. The fullRect() method accepts four arguments, similar to the getImageData() method. The first two values are the x and y values to start the rectangle. The third and fourth values are the height and width, respectively. Our rectangle draws all over the selected canvas.

Finally, set the RGBA value using the same data:


this.RGBA = data[0] + "," + data[1] + "," + data[2] + "," + data[3] ;

Now, run the code and start clicking away:

You can play with the app here, but because of cross domain issues with the image I couldn't upload it to a Plunker.

Final Thoughts

It was nice to delve into the canvas functionality of HTML5 as I don't get to deal with that in normal enterprise level development for most of my clients. I'm starting to get deeper into Angular 2 development.

Sign up for DotComIt's Monthly Technical Newsletter

Access an HTML5 Canvas -- Build a Color Picker in Angular 2 - Part 2

This is the second in a series of articles about building a color picker in Angular 2. The previous article focused on building the infrastructure and showing you how to use an external template in an Angular 2 component. This article will focus on creating the canvas, accessing it from Angular, and then using it to load an image.

Create Canvas

To create the canvas, open up the template, canvas.html. Add a canvas element:


<canvas id="imageCanvas" width="1024" height="768" style="border:1px solid #d3d3d3;" >
Your browser does not support the HTML5 canvas tag.
</canvas>

It is that easy. The canvas is named imageCanvas with the id tag. I specified a height and width which is equal to the image we'll use. I also gave the canvas a border. Beyond that, the canvas doesn't do anything yet.

Access Canvas in Code

Drilling into the HTML template to get a handle on the underlying canvas was harder to figure out than I thought it would be. The answer is to add a queries attribute to the AppComponent:


ng.core.Component({
selector: 'colorpicker-app',
templateUrl : '03canvas.html',
queries : {
imageCanvas : new ng.core.ViewChild('imageCanvas'),
}
})

The queries attribute creates a new viewChild. The name of the child is the same as the id we put to the canvas, so behind the scenes Angular will give us a hook to the HTML element so we can access it inside the class.

Load the Image

The final step for this article is to load an image into the canvas. I found a colorful creative commons image from Flickr that will do great for our demo.

To load an image onto the canvas, we need to get access to the imageCanvasContext, so create a variable for that inside the colorpicker-app's component constructor:


.Class({
constructor: function() {
var imageCanvasContext;
}
});

That just creates a variable, let's execute a method on startup:


this.onInit = function(){
}
this.onInit();

This is a convention I use commonly in my AngularJS 1 applications, and I'm just mimicking it here. I haven't decided if it is a good convention yet, but it works.

First, load the image:


var myImg = new Image();
myImg.src = 'ColorfulImage.jpg';

Easy enough! When the image has completed loading, we want to add it onto the Canvas. First, add a function for the onload() event of the Image:


myImg.onload = function() {
}

Inside the onload() function, get access to the 2D canvas context:


imageCanvasContext = imageCanvas.getContext('2d');

We need access to the context before we can draw on the canvas. Next, draw the image:


imageCanvasContext.drawImage(myImg, 0, 0);

This uses the drawImage() method on the canvas context. The image is placed at coordinates 0,0. Since we purposely sized the canvas to the size of the image, the image should cover the whole canvas.

Run the app:

View the app here. Unfortunately, I can't provide a link to a plunker for this sample because cross domain issues would prevent the image from loading.

What's Next?

The primary purpose of this entry was to show you how to get access to an HTML element inside a component's HTML. The final entry in this series will show you how to interact with the canvas, when it is clicked.

Sign up for DotComIt's Monthly Technical Newsletter

Use an External Component Template -- Build a Color Picker in Angular 2 - Part 1

This series of blog posts will document documents a quick little prototype I put together for a client. They wanted to be able to click on an image and get information about the color at the selected spot. It makes use of the HTML5 Canvas tag and is the most "Flash-like" thing I've done with HTML.

This first in the series will show you how to use an external template to an Angular 2 Component and how to access HTML Elements within that template.

Setup the App

The first step is to import all the Angular 2 libraries:


<script src="https://unpkg.com/core-js/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js@0.6.25?main=browser"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.8"></script>
<script src="https://unpkg.com/rxjs@5.0.0-beta.12/bundles/Rx.js"></script>
<script src="https://unpkg.com/@angular/core/bundles/core.umd.js"></script>
<script src="https://unpkg.com/@angular/common/bundles/common.umd.js"></script>
<script src="https://unpkg.com/@angular/compiler/bundles/compiler.umd.js"></script>
<script src="https://unpkg.com/@angular/platform-browser/bundles/platform-browser.umd.js"></script>
<script src="https://unpkg.com/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script>

Angular 2 is split into a lot of individual libraries instead of one big one like AngularJS 1.x branch. Next create the component:


(function(app) {
app.AppComponent =
ng.core.Component({
selector: 'colorpicker-app',
})
.Class({
constructor: function() {
}
});
})(window.app || (window.app = {}));

This is a typical Angular component. The name is colorpicker-app. We'll put a lot of code in the constructor later in this article. A template is not specified, but is required. We'll create that in the next section.

Next create the Angular module:


(function(app) {
app.AppModule =
ng.core.NgModule({
imports: [ ng.platformBrowser.BrowserModule ],
declarations: [ app.AppComponent ],
bootstrap: [ app.AppComponent ]
})
.Class({
constructor: function() {}
});
})(window.app || (window.app = {}));

The module declares our custom AppComponent and also bootstraps it. Finally, boot strap the main module:


(function(app) {
document.addEventListener('DOMContentLoaded', function() {
ng.platformBrowserDynamic.platformBrowserDynamic().bootstrapModule(app.AppModule);
});
})(window.app || (window.app = {}));

In the HTML body, use the colorpicker-app directive to load the component:


<colorpicker-app>Loading...</colorpicker-app>

Run the code as is:

Not too impressive, we get an error because of the missing template. There are two ways we could add a template.

Create an in-line template

It is easy to create an in-line template. Just add the template property to the colorpicker-app component definition:


ng.core.Component({
selector: 'colorpicker-app',
template : 'something'
})

Rerun the app:

I hate dealing with in-line templates because as the HTML gets wordy they are complicated to maintain and change.

Create the external template

We can create an external template using the templateUrl property:


ng.core.Component({
selector: 'colorpicker-app',
templateUrl : '02canvas.html'
})

The templateUrl property is put on the colorpicker-app component and replaces the template property we used in the last section. The templateUrl specifies the URL location of a template, in this case I refer to a template in the same directory, canvas.html:


Something in external template

The template code is just some text. Run the code:

When building AngularJS 1 applications, the templateUrl sometimes caused a problem with relative URLs after you ran the code through a build script with minimizers. This was because the location of the final minimized code was not always the location of the original code; and the browser wouldn't find the template. The same problem exists in Angular 2 applications. It can be solved by using a path relative to the root directory of the web server; but for now I kept it simple.

What's Next

I'm going to stop this article here. The next article will go into details on how create and access the canvas inside Angular 2.

Sign up for DotComIt's Monthly Technical Newsletter

Unhandled rejection Error: Not running at Server.close (net.js:1236:11) with Karma and Jasmine

I'm writing some addendum to my LearnWith AngularJS training series. One of those will detail how to unit test an AngularJS web application. I'm setting something up with Gulp, Karma, and Jasmine.

Trying to get this running gave me a full day of this error:


Unhandled rejection Error: Not running
at Server.close (net.js:1236:11)
at C:\Users\jhouser\Documents\career\clients\ActiveClients\LearnWith\Development\www_codearchive\Scripts_Test\node_modules\karma\lib\server.js:388:17
at tryCatcher (C:\Users\jhouser\Documents\career\clients\ActiveClients\LearnWith\Development\www_codearchive\Scripts_Test\node_modules\karma\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (C:\Users\jhouser\Documents\career\clients\ActiveClients\LearnWith\Development\www_codearchive\Scripts_Test\node_modules\karma\node_modules\bluebird\js\release\promise.js:510:31)
at Promise._settlePromise (C:\Users\jhouser\Documents\career\clients\ActiveClients\LearnWith\Development\www_codearchive\Scripts_Test\node_modules\karma\node_modules\bluebird\js\release\promise.js:567:18)
at Promise._settlePromise0 (C:\Users\jhouser\Documents\career\clients\ActiveClients\LearnWith\Development\www_codearchive\Scripts_Test\node_modules\karma\node_modules\bluebird\js\release\promise.js:612:10)
at Promise._settlePromises (C:\Users\jhouser\Documents\career\clients\ActiveClients\LearnWith\Development\www_codearchive\Scripts_Test\node_modules\karma\node_modules\bluebird\js\release\promise.js:691:18)
at Async._drainQueue (C:\Users\jhouser\Documents\career\clients\ActiveClients\LearnWith\Development\www_codearchive\Scripts_Test\node_modules\karma\node_modules\bluebird\js\release\async.js:138:16)
at Async._drainQueues (C:\Users\jhouser\Documents\career\clients\ActiveClients\LearnWith\Development\www_codearchive\Scripts_Test\node_modules\karma\node_modules\bluebird\js\release\async.js:148:10)
at Async.drainQueues (C:\Users\jhouser\Documents\career\clients\ActiveClients\LearnWith\Development\www_codearchive\Scripts_Test\node_modules\karma\node_modules\bluebird\js\release\async.js:17:14)
at process._tickCallback (node.js:419:13)

There is a lot of Google hits for this error; but none actually relate to my issue, so I hope this helps someone.

After much head pounding and experimentation; I finally deciphered the cause. When creating the Karma config file, make sure that your files are put in proper dependency order. Simply put; I was listing the AngularJS library at the end of the file list instead of the beginning, so the code didn't know how to create angular modules, services, or other elements, because that Angular library wasn't defined yet.

Changing the order of dependencies solved the issue and I can run unit tests as expected.

I hope that helps someone.

Sign up for DotComIt's Monthly Technical Newsletter

Button Clicks - Introduction to Angular 2 with JavaScript - Part 3

This is the third in a series about building a simple AngularJS application. If you haven't already, check out part 1 and part 2.

Review

In part 1 we built a simple component that displayed a template to the screen. In part 2 we showed how to bind a Class variable to an input and a display. Let's review the Angular component code:


(function(app) {
app.AppComponent =
ng.core.Component({
selector: 'my-app',
template: '<h1>Hello {{helloTo}}</h1>' +
'<input type="text" [value]="helloTo" (input)="helloTo=$event.target.value" /><br/>' +
'<input type="text" [(ngModel)]="helloTo" /><br/>'
})
.Class({
constructor: function() {
this.helloTo = "World"
}
})
})(window.app || (window.app = {}));

The component is wrapped in an IIFE function; and the Angular application is stored in the window.app variable. The component is given a selector, my-app, which is in essence the name. The template includes two inputs demonstrating two different ways to bind to values in Angular 2.

The Class contains a single variable, helloTo, which is used as the source for binding.

Change the Template

Another common element required when developing applications is to run code when a button is clicked. In Angular 1 we used the ngClick event. Angular 2 uses a similar concept, but is slightly different implementation syntax. Here is the component's template as a reminder:


template: '<h1>Hello {{helloTo}}</h1>' +
'<input type="text" [value]="helloTo"
(input)="helloTo=$event.target.value" />
<br/>' +
'<input type="text" [(ngModel)]="helloTo" /><br/>'

The template consists of a header which binds to the helloTo variable. It has two inputs, both representing different methods to change the helloTo variable.

We'll add one more item to the template. Here is a button:


'<button (click)="onReset()">reset</button><br/>' +

I put the button after the header, but before the inputs. Instead of using an ngClick directive, the directive is named click, and is enclosed by parenthesis. The click statement on the button will call a method inside the component's class.

Create the Click Handler

We want to the button to reset the helloTo variable to its default value, World. After the helloTo variable is created in the Class, add a function named onReset():


this.onReset = function(){
this.helloTo = "World";
}

Run the code, and you should see something like this:

Change one of the inputs, and click the reset button. The app should go back to its default state.

Play with the code here

Final Thoughts

I enjoyed my experiments with Angular 2 and JavaScript. Based on available documentation, I'd be cautious about jumping into Angular 2 deep at the time of this writing. If I were going to; I'd focus on TypeScript. The full documentation for JavaScript is not there yet and most of the community questions revolve around TypeScript answers, which are not always easily portable to JavaScript. Despite all this; I'm cautiously optimistic about our Angular 2 future.

Get our Intro to Angular 2 White Paper

More Entries

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.