Check out our new training course on AngularJS for Flex Developers

Passing Values into a Directive - Building Angular Directives - Part 3

This is the third post in a series about building Angular Directives. The purpose is to create a directive which will loop over a list of items, and allow the user to delete one of the items. The result will look something like this:

This post will focus on passing values into a directive.

Be sure to check out part one and part two.

Creating an Isolated Scope

An important aspect of building an encapsulated directive is to be able to pass data into it. This way, you can create multiple instances of a single directive, each using different data. Past entries of this series have relied on a local controller for data access. This entry will show you how to pass parameters into a directive by implementing a concept called isolated scope.

The first step to create an isolated scope is to add the scope variable to the directive object:


angular.module('directiveTestApp').directive('dciTestdirective',function(){
return {
scope : {
dataprovider : '=',
label : '=labelfield'
},
templateUrl : currentScriptPath + '04ExternalTemplate.html'
};
});

The scope variable is an object, which contains name values pairs. This directive contains two arguments:

  • dataprovider: The dataprovider argument will contain the array which is going to be looped over.
  • labelfield: The labelfield argument contains the property in the dataprovider's objects that will be used to display items.

I want to look at each scope value individually, and the syntax used to create it. Here is the label definition:


label : '=labelfield'

The variable name is label. This represents the name of the scope variable inside the directive. You will use the name label to reference this inside the template. The value of the variable is '=labelfield'. This refers to the attribute name that will be used when passing vales into the component. For the purpose of the label, I decided to use a different internal name than the external name.

Here is the dataprovider:


dataprovider : '='

The variable name is dataprovider. The value of the variable is just an equal sign, '='. This is a short hand way to tell Angular that the name of the variable inside the directive will be the same as the name of the attribute outside of the directive. In both cases, the name dataprovider is used.

I want to point out that the names of the properties are written all in lowercase. The attributes must be written in lowercase in order for Angular to properly sync the external attribute with the internal attribute. I have lost too many hours because I forget about the case sensitivity of scope variable names.

Referencing the Scope Variables in the template

Let's modify the template to reference the new scope variables. Previously the template was referencing variables in the scope of the controller, like this:


<div class='dciTestdirective-width100' ng-repeat='object in objectArray'>
<span class='dciTestdirective-horizontal-layout-94'>
{{object.itemLabel}}
</span>
<span class='dciTestdirective-horizontal-layout-4'>
<button >X</button>
</span>
</div>

We can change both the objectArray and the itemLabel values to reference our directive's scope variables:


<div class='dciTestdirective-width100' ng-repeat='object in dataprovider'>
<span class='dciTestdirective-horizontal-layout-94'>
{{object[label]}}
</span>
<span class='dciTestdirective-horizontal-layout-4'>
<button >X</button>
</span>
</div>

Changing the objectArray to the dataProvider is easy and a simple replacement. Since the item label is not a known value, object property notation cannot be used. In order to access the label, we use associative array notation. That completes the modifications to the template.

Passing Parameters into the Directive

The last step to get this working is to modify the directive to include the parameters in the main HTML page:


<dci-testdirective dataprovider="objectArray" labelfield="'itemLabel'">
</dci-testdirective>

The custom directive includes the two attributes we defined in the scope; the dataProvider and the labelfield. The dataProvider attribute references the objectArray; which is defined in the controller. The labelfield uses a hard coded string value which references the itemLabel property in the dataprovider's objects.

You can run the code now, and should see this:

Play with this now!

Even though the underlying architecture of the directive has changed; the actual UI has not.

Using the Directive with a Different Data

One of the benefits of creating the isolated scope is that you can use the directive multiples times with different data. Inside the controller of the main app, create a new array:


$scope.userArray = [
{fullName:'Jeffry Houser'},
{fullName:'Clark Kent'},
{fullName:'Oliver Queen'},
{fullName:'Barry Allen'},
];

This array, instead of being a generic objectArray is now a user array. It contains real fake user data which includes a user's full name.

You can easily add another instance of the dciTestdirective to the main HTML:


<dci-testdirective dataprovider="userArray" labelfield="'fullName'">
</dci-testdirective>

The directive usage is the same, but the userArray and labelfield attributes both reference the new properties.

Run this code!

What Next?

Giving the directive an isolated scope allows the directive to be easily reusable. I focused on how to get data into a directive; but the same approach is used to get data out of a directive. When the value inside the directive changes the variable outside the directive also changes.

In the next entry of this series, I'm going to show you how to set default values on the scope variables.

Sign up for our 30 page white paper on Angular Directives

Using External Templates - Building Angular Directives - Part 2

This is the second post in a series about building Angular Directives. The purpose is to create a directive which will loop over a list of items, and allow the user to delete one of the items. The result will look something like this:

This post will focus on moving the directive's template into an external file.

Be sure to check out part one of this series.

Create a Template

I find that inline templates are hard to modify. This becomes a problem as the template grows in complexity and size. No one wants to edit HTML as if it were a large string. Thankfully Angular supports the use of an external template.

First, let's revisit our existing directive:


angular.module('directiveTestApp').directive('dciTestdirective',function(){
return {
template: "<div ng-repeat='object in objectArray'>
<span>{{object.itemLabel}}</span>
<button>X</button>
</div>"
};
});

This directive loops over an array of objects and displays them. The directive object has one property, named template. Let's move the template contents to an external template.

Create a file named 02ExternalTemplate.html. The 02 in front of the name tells us that this file is part of the second sample for this article series. The text tells us what the file is used for. Populate the file with some cut and paste:


<div ng-repeat='object in objectArray'>
<span>{{object.itemLabel}}</span>
<button>X</button>
</div>

That is simple. Now let's tell the directive how to use the template.

Tell the Directive to use an External Template

The original directive uses the template property on the directive object. We are going to replace it with the templateUrl property. The templateUrl property tells Angular to look at an external file for the template:


angular.module('directiveTestApp').directive('dciTestdirective',function(){
return {
templateUrl : '02ExternalTemplate.html'
};
});

Run the code as is, and you'll see the same screen you saw before.

Changing the underlying architecture has not changed the HTML page.

Add Some Styles

While we're creating the external template, let's add some styles to make it look a bit nicer. For the sake of this sample, I'll add the styles directly to the external template file. First, I'll show you the styles to create and then we'll modify the HTML to use the styles.

First, I want the directive to expand the full width of the container it resides in. I can do this with a style like this:


<style>
.dciTestdirective-width100 { width:100% }
</style>

Next, I want the item label to spread as far as it needs; while the x button should take up a smaller portion of the available space. First, the style for the label:


.dciTestdirective-horizontal-layout-94{
display: inline-block;
vertical-align: top;
width:94%;
height:100%;
}

The style code can go in the same style block as the width100 style. The display property is set to inline-block so that the two elements reside next to each other.

This is the style for the button:


.dciTestdirective-horizontal-layout-4{
display: inline-block;
vertical-align: top;
width:4%;
height:100%;
}

The style for the button is almost identical to the style for the label. The big differentiator is that the width is set to a different percentage.

Now look at the modified HTML:


<div class='dciTestdirective-width100' ng-repeat='object in objectArray'>
<span class='dciTestdirective-horizontal-layout-94'>
{{object.itemLabel}}
</span>
<span class='dciTestdirective-horizontal-layout-4'>
<button >X</button>
</span>
</div>

The top level div uses the dciTestdirective-width100 style to stretch the box the full width of its container. The label is put in a span and uses dciTestdirective-horizontal-layout-94. The button is put in a different span with the style of dciTestdirective-horizontal-layout-4, giving it 4% of the allotted space.

The button was not previously wrapped in an HTML element. I did this because I wanted to change the size of the space the button was in; but not the actual button size.

The final result should look something like this:

Play with it here!

When creating styles for a directive, I like to explicitly put the directive name in the style name. The intent is to avoid conflicting style names when used in a bigger app, with multiple style sheets.

Find the External Template, Relative to the JavaScript File

When building for reuse I don't want to make assumptions on the location of the directive, relative to the web root. As such, I do not like hard coding the location of the template file. I found a great approach for dynamically finding the external template relative to the JavaScript file.

First, get a hook to the script tag:


var scripts = document.getElementsByTagName("script")

Then, pull the src attribute to the script tag:


var currentScript = scripts[scripts.length-1].src;

Now we have the location of the JavaScript file. Next, pull the file name off the currentScript to get the current path:


var currentScriptPath = currentScript.substring(0, currentScript.lastIndexOf('/') + 1)

Finally modify the templateUrl property of the directive:


return {
templateUrl : currentScriptPath + '02ExternalTemplate.html'
};

Rerun the directive and you should see the exact same screenshot as before. I like to put the script processing as part of the directive code before the return object.

Check out the live sample.

What Next?

This post covered two aspects of directive development: moving the HTML code to an external template and adding some simple styles to the directive. For the purposes of this sample, the CSS was kept inline as part of the template file. When building more complex systems, I'll put the styles in their own CSS file. To make use of the directive, the consumer must include the directive JavaScript and the CSS.

Next I'll show you how to pass values into the directive, thus removing the dependency on specific variables defined in the controller.

Get our 30 page white paper on Angular Directives

A Simple Directive - Building Angular Directives - Part 1

This is the first in a series of blog posts about building Angular Directives.

An AngularJS Directive combines HTML and JavaScript code into a single unit that can be easily reused within an Angular application. This series is intended to explore Angular directives, with a focus on optimizing the directive code for reuse.

Our Directive

The directive we're going to create in this paper will generate a list of items. It will loop over an array of items, and display each item, along with a delete button. The final directive will look something like this:


In this series, you'll learn how to setup the directive, use external templates for HTML, send values into the directive, run functions when something in the directive happens, and how to call functions inside the directive. This first section will create a basic directive which we will iterate over throughout this series.

Create the App Infrastructure

The first thing we need to do in any AngularJS project is to import the framework:


<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js">
</script>

The Angular framework is imported using the HTML Script tag. Next, create the Angular module:


<script>
angular.module('directiveTestApp',[]);
</script>

The Angular module is named directiveTestApp and there are no arguments passed into the directive. The rest of our JavaScript code for this article will go inside this script tag.

Every Angular app needs a controller:


angular.module('directiveTestApp')
.controller('directiveTestController',
['$scope',
function($scope){
}
])

There is no content in the main controller yet, but we'll come back to that.

Next, create the HTML code for this application:


<body ng-app="directiveTestApp">
<div ng-controller="directiveTestController">
</div>
</body>

The HTML UI is empty for the moment; but the module name is added to the body tag with the ngApp directive. The directiveTestController is added to a div with the ngController tag. If you have experience with Angular applications, then this approach should be familiar.

One last thing I want to do in the controller is to create the array of items that the directive will loop over. Inside the controller, create a JavaScript array:


$scope.objectArray = [
{itemLabel:'item1'},
{itemLabel:'item2'},
{itemLabel:'item3'},
{itemLabel:'item4'},
{itemLabel:'item4'}
];

Now we are set to create our first directive.

Creating a Simple Directive

An Angular directive is created as part of an Angular Module. A directive function is used. It requires two arguments, similar to how services, controllers, and other Angular elements are created. The first argument is a string that specifies the name of the directive. The second is a function which defines the directive's functionality.


angular.module('directiveTestApp').directive('dciTestdirective',function(){
});

The directive is named dciTestdirective, and I'll talk more about naming in a second. Right now the directive doesn't do anything, and if you were to try to use it, Angular would return an error. The directive function must return an object that contains properties which define the directive. In this case, we are only going to specify a single parameter, the template:


return {
template: "<div ng-repeat='object in objectArray'>
<span>{{object.itemLabel}}</span>
<button >X</button>
</div>"
};

The template contains some in-line HTML. It loops over the objectArray; which was created in the app's controller; and displays the itemLabel along with an X button.

Now add the directive to the HTML, inside the controller:


<dci-Testdirective></dci-Testdirective>

Run the code and you'll see this:


Play with this sample here.

How do you name a Directive?

Naming of directives is a subject that should be approached with care. When I first started learning directives, this confused me. The key is to understand that there are two parts to each directive, the prefix and the directive name. When naming a directive with the directive function, the prefix should start in all lowercase. The name starts with a capital letter. So, in the case of our directive the prefix is dci--which is short for DotComIt, my company. The name is Testdirective.

When Angular parses the DOM, it looks for selectors, such as element names or arguments, using a specific formula that is called normalization. Our directive, named dciTestdirective could be written in any number of ways in the HTML template:

  • dci-testdirective
  • dci: testdirective
  • dci_testdirective
  • data-dci-testdirective
  • x-dci-testdirective

If Angular finds something in one of the above formats, it runs it through a process called normalization. Then this process occurs:

  1. The name is put into all lowercase.
  2. x- or data- are stripped from the front of the element or attribute.
  3. The delimiters are removed. The dellimiters are the colon (:), dash (-), or underscore (_).
  4. The first character after the delimiter is made into uppercase.

When creating a directive, you must name it properly or else Angular won't know how to match the use of the directive to the actual directive code.

For practical purposes, I always use the dash (-) as a separator between the directive prefix and the directive name. I never put use the prefix x- or data- with my directives.

What Next?

The current directive is lacking. Here are some problems:

  • The objectArray must be defined in the controller where you use the directive. This is not good use of encapsulation. The directive should have its required parameters passed to it using a defined API.
  • The template is created in-line as a single string, which makes it hard to change or edit.
  • The in-line template could be styled to improve its look.
  • The functionality is not yet complete. The 'x' button does nothing yet, and the directive offers no other way to interact with the data it displays.

We'll iterate over this directive throughout this series in order to flesh this out. Next week, I'll discuss using an external template.

Sign up to receive our 30 page white paper on Angular Directives

How do I stop my Displayport Monitor from Flickering?

I've had this annoying flickering on my monitor every time I open Thunderbird. The screen would sporadically blink in and out of existence. I've seen the same problem in other programs, but Thunderbird was the most prominent. It was usable, but annoying. I just accidentally found the fix and wanted to document it in case others are experiencing the same issue.

First,let me tell you a bit about my setup:

I'm using a desktop Windows computer with an AMD Radeon 7750 video card.

The DisplayPort out of the video card goes into an AdderviewPro Displayport KVM Switch.

From there, the KVM Switch connects to a Dell U3011 30 inch Monitor. The monitor resolution is set to 2560x1600.

When the blinking occurred, I always thought it was due to the KVM Switch. I've always had mixed luck with KVM Switches--but when you have multiple computers at your desk I think the benefit outweighs the problems. [Other computers connected to the KVM Switch do not exhibit the same blinking problems].

I was reading up on some completely unrelated problems with my Surfacebook's dock and decided to dig into the blinking issue. I was wondering if changing the refresh rate would have an affect. I poured over options in the Radeon Settings panel:

Nothing seemed to make sense. Then I clicked the "additional settings" button:

After that, I noticed the preferred color depth setting. It was set to 10. As an experiment I changed it back to 8. Immediately all the blinking problems were gone. I'm not sure what the affects are from setting the color depth from 10 to 8. As best I can tell; the computer appears to be working as expected. I'll keep an eye on it to see if I run into any problems.

I've been using this for a while now without any problems. I have to admit I'm pretty shocked. I'm not sure what is more frustrating; that I lived with this for so long and it had an easy fix or that the problem existed in the first place.

Hopefully this helps someone.

How do I Copy Specific Text to the Clipboard using in JavaScript?

In some previous blog posts, I wrote about copying text to the clipboard using a ClipboardJS library. I demonstrated how to copy text from an input text field, and how to cut text from an input text field. I wanted to follow up that article to show you how to copy predefined text that the user can't edit.

Using ClipboardJS to Copy Specific Text

The first step in using the library is to import the library:


<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.5/clipboard.min.js"></script>

Once the library is imported, we must initialize it:


<script>
new Clipboard('.btn');
</script>

The initialization process uses JavaScript's new keyword to create an instance of the Clipboard object. The argument refers to the item in which the Clipboard library will listen for copy events. In this, case we are telling the library to look for all elements where the class was named 'btn'. On said elements, the library will look for special attributes that tell the library how to operate.

Now, create a button to perform the copy:


<button class="btn" data-clipboard-text="Some Predetermined Text">Copy Predetermined Text</button>

This button uses the class btn; which is the name of the class we used when initializing the Clipboard object. The clipboard library looks for the data-clipboard-text attribute; which is uses to determine what text should be copied. We can specify any text in the data-clipboard-text argument.

That is all we need to copy the text; the library takes care of the rest.

Test this out.

Sign up for DotComIt's Monthly Technical Newsletter

How do I find documentation for old versions of UI Bootstrap?

I have been doing a lot of development with AngularJS and Bootstrap. For Bootstrap components, I have been using the UI Bootstrap library. UI Bootstrap is a version of Bootstrap rewritten as Angular directives. It works well, however seems to be in constant flux. Each new version contains changes and reworks and as such different versions are incompatible with each other.

When I start an existing project; I use the most recent version; but I have multiple projects with different clients using the older versions. Upgrading is not usually in the budget. Why would a client want to pay to change something that already works? As such, it is beneficial for me to look at older documentation when making changes; since the most recent documentation is no longer relevant.

So, how do I find the documentation for the older releases?

Just take this URL:

http://angular-ui.github.io/bootstrap/versioned-docs/0.13.3/

Specify the version number you are looking for. Here are a few options:

The site only archives documentation starting with 0.12.0 on, and they are available using a drop down menu in the main nav bar of the UI Bootstrap site.

I used 0.6.0 for my training course on AngularJS. Version 0.8.0 of UI-Bootstrap is the last one to support the Bootstrap 2; all updates after that support 2.3.

If you need these earlier docs; you'll have to check out an earlier version from the repository.

The Future of Flex and the Flash Player

This question comes in from a reader, about the future of Adobe Flex and the Flash Player:

Hello Jeffry, I know you because some answers your in StackOverFlow.

But my contact is because in Brazil we company is totally based in Adobe Flex used Flash builder 4.6 and AIR for mobile, and I would know you suggestion about future of Flex and flash.

I believe that programming for long year ahead because all programmer in my company lover Flex but sometime I have fear Adobe finish Flash player and my apps canĀ“t running in my clients.

I wrote a lot about the future of Flex in the past.

But, all those posts are few years old. What do I think today?

First, I am not an Adobe employee and am no longer part of the Adobe Community Professional program. I cannot offer any personal insight into what Adobe may do with the Flash Platform.

I do think the Flash Platform will be around for a long time. However, I do not see Flash as a growth area.

It is very difficult for me to run a Flash Debug Player on my Surface Book

Most new browser based applications are written using HTML5-based technologies. I have had success with AngularJS in the HTML5 world. I even wrote a training course about AngularJS for Flex Developers.

AIR for mobile seems a lot more viable than the browser based Flash Player. I know a lot of gaming companies still use AIR for mobile deployment.

In terms of Flex, the Apache Flex team has done wonderful things with Flex. Since you're still on Adobe Flex; I recommend you consider upgrading to the latest version of Apache Flex.

If your clients do not have problems running your apps today; I'm sure they'll continue to run them throughout the next year without any problems.

For those out there who are considering re-writing your apps to use HTML5 tools; feel free to reach out. I am available for consulting, training, or mentoring.

How do I copy an object in AngularJS?

I was recently working on an AngularJS project for a client. Some data was shown on a screen, and the user would click an edit button to open the same data in a popup modal. The problem I ran into was that any items changed in the popup where automatically changed in the main screen. This was causing some undesirable side affects. What if the user decided to cancel their changes or close the popup? The main screen would be affected.

I Decided to get around this by creating a copy of the object in question. I sent that copy to the popup; then when the popup is closed I can check whether the data was saved and make changes in the main app. But, if the changes in the popup are cancelled, I can dismiss the popup without having to modify the main app.

The question is; how do I perform a deep copy of an object in AngularJS? Use the copy method.

Here is how you can set up an application.

First, import the Angular framework, create a sample module, and a controller:


<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>
<script>
angular.module('copyTest',[]);
angular.module('copyTest').controller('copyController', ['$scope', function($scope){
}]);
</script>

For this demo, create two separate objects, the baseObject and the objectCopy. The baseObject will contain a mock user object, with an id property, a firstname property, and a last name property:


$scope.baseObject = {
id : 1,
firstName : 'Jeffry',
lastName : 'Houser'
}

The objectCopy will initialize as an empty object:


$scope.objectCopy = {};

I'll build out a UI For editing object properties; then come back to the script:


<body ng-app="copyTest">
<div ng-controller="copyController">
<h2>Base Object</h2>
ID: <input type="text" ng-model="baseObject.id"> <br/>
First Name: <input type="text" ng-model="baseObject.firstName"><br/>
Last Name: <input type="text" ng-model="baseObject.lastName"><br/>

<h2>Copied Object</h2>
ID: <input type="text" ng-model="objectCopy.id"> <br/>
First Name: <input type="text" ng-model="objectCopy.firstName"><br/>
Last Name: <input type="text" ng-model="objectCopy.lastName"><br/>


<br/><br/>
<button ng-click="onCopy()">Copy Object</button>
<button ng-click="onReset()">Reset Base Object</button>
</div>

This app adds the Angular module onto the ngApp tag and the ngController onto a div. The user properties on both the base object and the copied object are put into text inputs. I also add two buttons, one to perform a copy from the base object to the objectCopy; and a second to reset the base object to its default values.

Load the app and you should see something like this:

Now, let's implement the onCopy() and onReset() methods. onReset() sets the baseObject to it's default state:


$scope.onReset = function(){
$scope.baseObject = {
id : 1,
firstName : 'Jeffry',
lastName : 'Houser'
}
};

The objectCopy is untouched.

The onCopy() method copies the base object into the objectCopy object and the baseObject is untouched:


$scope.onCopy = function(){
$scope.objectCopy = angular.copy($scope.baseObject);
};

Load the app and play with the options. This demo shows that edits to one object are not going to have an affect on the other object.

Modify the base object and click the copy button. The objectCopy fields will be populated with data. Change the objectCopy fields and the baseObject fields are not affected. Reset the baseObject and you'll see the objectCopy is not affected.

Play with the code here.

Sign up for DotComIt's Monthly Technical Newsletter

How do I Copy to the Clipboard with AngularJS?

Last week I wrote about using ClipboardJS to copy text the Clipboard using JavaScript. I wanted to extend on that article and show some examples of how to use that library within the context of an AngularJS Application.

ClipboardJS and AngularJS can exist in the same HTML page. This is my preferred approach for using the two together.

First, import the Clipboard and Angular libraries:


<script src="//cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.5/clipboard.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>

Next, create an Angular module:


angular.module('clipboardTest',[]);

Now the Clipboard library must be initialized. This could be done with any random JavaScript code, but I like to do it in an Angular config block:


angular.module('clipboardTest').config( function(){
new Clipboard('.btn');
});

Next, create an Angular controller:


angular.module('clipboardTest').controller('clipboardController',['$scope', function($scope){
$scope.someValue = "Some Text";
}])

The controller creates a single value and puts it in the $scope. We'll use the $scope value as the target value for the ClipboardJS library.

Let's put together the UI Behind this app:


<body ng-app="clipboardTest">
<div ng-controller="clipboardController">
<input id="input" value="{{someValue}}">
<button class="btn" data-clipboard-target="#input">Copy</button>
<button class="btn" data-clipboard-action="cut" data-clipboard-target="#input">Cut</button>
</div>
</body>

The Angular module is put on the body tag with the ngApp attribute. Inside that is a div with the controller. Three elements are inside the angular view. The first is the text input. This uses the Angular binding syntax of double curly brackets to display $scope.someValue from the controller in the view. This input is the target for the clipboard library. The two buttons are identical to what we used in the previous sample.

Running the app, you'll see that the app with Angular works the same as the example from my previous article, without Angular in the mix. The use of Angular is just some syntactical sugar.

Play with the app here.

I'm sure that ClipboardJS could be rewritten as an Angular directive; but it is not required to use the two together.

Sign up for DotComIt's Monthly Technical Newsletter

Using the Surface Book as a Programmer - Four Months In

I am the owner of a Surface Book; Microsoft's premier Windows Laptop/Tablet Hybrid. I've been meaning to write a review about it. As I start this, I'm downloading a new Windows ISO while attempting to apply a fix for corrupt display files and thought I'd take some time to put down my thoughts.

Here is all the good and bad about the Surface Book, according to a programmer who has used it for 4 months.

Getting a Surface Book?

I'm a small business owner and try to replace my main work machine every four years or so. My Thinkpad had started to make a sporadic horrible noise for no discernible reason, so I was in the market for a new laptop. The Surface Book was announced a couple of weeks after this fan noise started. You don't often see windows laptops with the design sense of a Mac. I decided to go all in. I pre-ordered the day after it went on sale, but had numerous pre-order problems, documented elsewhere. Eventually, I got a Surface Book on Friday October 30th. It has been my primary dev machine for about four months at the time of this writing. Here is my attempt at an unboxing video:

Who Am I?

My business cards say "Technical Entrepreneur." I'm a small business owner looking for opportunities to do cool things and share them with others. Primarily I make money building business applications. Someone else makes it pretty, but I make it functional. I've worked with many brilliant designers--but that isn't me. I'm the guy who makes things work.

For daily use; I need a computer that can run multiple development programs. In any given day, I'll use IntelliJ, Eclipse, NodeJS, ColdFusion, PHP, Apache, Java, Flash, Remote Desktop, SQL Server, MySQL and multiple browsers with dozens of active tabs.

I am a writer, and occasional screencaster. I write one technical blog post a week. I created a training course on AngularJS for Flex Developers, which includes over four hours of screencasts on AngularJS. I write game reviews for JustAdventure.com. Having a laptop that can play computer games is a nicety especially if I'm on the road for a client and need to pass the time in a hotel or while in transit.

The bulk of my work is done out of a home office, so on normal days I have my Surface Book docked, with an external keyboard, mouse, and monitor. The reason for having a laptop is because it is great to have my work with me when I am meeting with clients.

So, as a quick summary. I need a laptop for:

  • Programming
  • Writing
  • Screen Recording
  • Moderate Gaming

I was pretty sure the Surface Book would fit the bill, plus had some cool factor related due to the hybrid nature. I decided to go for it. How did it do? Read on!

First Impressions

There is a lot to love about the Surface Book. The construction is solid in my hand. The trackpad is responsive and easy to use. The keys are light to the touch. I have no problem typing in the keyboard, despite using an external mechanical keyboard at my desk.

The screen is the highlight of the machine. Words cannot express how beautiful this screen is. I was worried that the extra-large resolution on a relatively tiny display would make most programs unusable; but that is not the case. Many install programs, such as the ColdFusion server, were difficult to read; but once the install completed, the programs run smoothly.

The bulk of the internals are in the Clipboard section. Usually the screen is the lightest part of the laptop, but here it is the heaviest. I've heard some worries that this weight distribution will cause issues when using the unit on your lap. I adjusted to this very quickly. Microsoft created a dynamic fulcrum hinge to support the heavy Clipboard. The hinge does its job well and the unit is perfectly serviceable in your lap. The Clipboard on its own is surprising light. It surprises people when they feel it. It looks too big to be this light.

The hinge doesn't allow the clipboard part of the machine to lay flat against the keyboard, leaving a gap when the Surface Book is closed. Some have worried that items would get stuck inside the Surface Book while it was in their bag. I have not had that issue. I use a laptop backpack with a special laptop compartment, which protects the unit from interacting with other loose items.

The machine loads faster than any Windows machine I've ever used. Boot times are iPad-like. Surface Books use two different brands of hard drives, a Samsung or Toshiba. I got the Samsung, which is the slower drive. Hard drive access is just one aspect of overall speed; and I suspect you'd be hard pressed to notice slow-downs even if you were comparing two machines side by side. The Internet led me to believe that the 128GB machines will have the biggest performance differences in hard drive performance. The 512GB version is plenty fast for my purposes.

The battery life is great. I can spend a day with clients in New York City and do not have to plug the laptop in at all. The commute is three hours one way, so this is a 12-hour day minimum. I get home with battery life to spare. Like many new devices today, the battery for the Surface Book is not removable. I have some fear this may cause long term issues. With past laptops I've lengthened the life of the machine by replacing the battery.

The Surface Book's screen resolution is 3000 by 2000, which is pretty high for a 13 inch screen. The bulk of software I run is DPI aware and adjusts itself accordingly. Programs even adjust when moving between the Surface Book's High DPI screen to a 'normal DPI' external monitor. Some programs, such as Eclipse, needed to be told to run in the High DPI resolution mode. Otherwise everything looks too small. I use this approach to tell programs to ignore the high DPI. You can also set this in the compatibility settings for the program's executable.

Before we move on, here is a vid I created of detaching and re-attaching the Clipboard:

Programming on the Surface Book

My Surface Book has 16GB of RAM and it has no problem running all the software I need for programming. Right now, I have IntelliJ, Chrome, Firefox, Edge, Apache, SmartGit, and ColdFusion running in the background. Not to mention Word and Notepad. The machine handles all of this--and often more--like a champ.

Keyboard Remapping

When coding I use the right control key and the right and left arrow key to move between words. This is a quick navigation through lines of code, often moving forward or back to change or copy a variable name. Unfortunately, the Surface Book keyboard does not have a right control key:

After some struggling, I decided to use a keyboard remapper to remap the 'context menu' key to act as a right control. SharpKeys from CodePlex, made this very easy. I think under the hood it makes a registry change. This makes my life a bit easier and I don't have to relearn years of muscle memory training.

Flash Development

I come from a background as a Flex Developer. Flex is a programmer's way to make Flash movies and for a while it was a very successful way to create business applications. New Flex development is rare now, but I still handle maintenance requests from clients; both old and new. Arguably I'm one of the world's most prominent Flex developers, so I don't often turn down the work. Flash development is a problem on the Surface Book because there is limited support for the Flash Debug player. Let's look at the browsers:

  • Edge comes with a built in Flash Player and there is no way to replace it with a Flash Debug Player. (Source 1 and Source 2)
  • Internet Explorer 11 comes with a built in Flash Player and there is no way to replace it with a Flash Debug Player. (Same Source as Above)
  • Chrome does support a Flash Debug player, but it is tough to install. To use the Flash Debug player you must launch Chrome with the -disable-bundled-ppapi-flash flag. I'm not sure if that is possible when launching from Eclipse/Flash Builder and haven't gotten around to trying it.
  • Firefox does support the Flash Player debug version. However, there is an error with Flash inside Chrome on High DPI Screens. You can disable the display scaling for Firefox, as mentioned previously; but this solution only worked for Browser Flash is I had an external monitor plugged in.

So, Flash Development is tough and has prevented me from taking the old laptop off my desk.

Writing on the Surface Book

The Surface Book would be great for writers. It runs Word wonderfully. My blogging software is browser based, and there are no issues accessing it on the Surface Book.

Writing with the Pen

I'm routinely in New York City to visit clients. On the way home, I'll take out the Clipboard, Pen, and use OneNote to brainstorm song lyrics for my music-related hobby. It works astoundingly well.

One of my desired use cases for the Surface Book was to use it take notes at client meetings. Automatically digitizing the notes and syncing them to my phone would be a great time saver. Unfortunately, when in meetings with clients I often need to share my screen to load a web site or presentation or other information. During such time it is not practical to share the screen I am using to take notes on. I never use the Surface Book for this use case. Instead of carrying around a second laptop for sharing, I now stick with the paper notepad and pen for my meeting notes.

Drawing with the Pen

Since I'm on the topic, I think the Surface Book pen and touch screen would be great for artists. I find the pen very responsive both when writing and when drawing. This is something I drew with Freshpaint as an experiment:

This is about as good as I'm able to draw. I'm sure a trained designers or artists would do much better.

Gaming on the Surface Book

I've had mixed experiences with gaming on the Surface Book. I downloaded Minesweeper, Solitaire, and a Sudoku game from the Windows App store. They all work great. The Firefox Flash bug prevents me from playing my casual game addiction, Bloon Monkey City. The game screen is too small. Other browsers I've tried zoom differently than Firefox does; so that makes the game too large.

Games I review for JustAdventure are primarily point and click adventure games. Most of them are not taxing to recent computers. To date, I've only tried to install one point and click adventure game, the Book of Unwritten Tales: Critter Chronicles. It gives an error about a dll missing from the computer. I was able to find some documentation on this error, but none of the fixes worked. I eventually gave up and moved back to my main desktop for gaming.

I know based on Surface forums a lot of people are having great success gaming on the Surface Book. I think my experience is too limited to draw any long-term conclusions. This was never my prime use case.

What is wrong with the Surface Book?

I have a list of problems I've had with the Surface Book and I've kept notes. Many of the issues have gone away with updates. Some problems are brand new, thanks to those same updates. I've separated this list into current problems and sporadic / fixed problems.

Sporadic and One-Time Issues

Here are some issues that have only happened once or twice then went away never to return:

  • Display Driver Crashes: Display driver crashes were common in the first few weeks of using the machine. A message showed up in the bottom right corner about it. These errors went away and I haven't seen it in months. This is the type of error I liked because the display driver would reset itself w/o a machine reboot or any other input from me. I just had to deal with a notification that went away on its own.
  • No Trackpad: Sometimes the machine's track pad wouldn't work. This was sporadic and may have had something to do with waking up from sleep mode, but I'm not sure. A reboot fixed the error every time.
  • Blue Screens: On my first full day using the computer as my primary dev machine; I saw two blue screen crashes. They were common in the early days, but I haven't seen one in months.
  • Battery Power when plugged in: When disconnecting Clipboard and plugging it back in; the Surface uses battery power instead of the dock power. The solution is unplug the dock and plug it back in. I saw this error twice, then had an update and it went away, I hope forever.
  • Master Volume Doesn't Work: The master volume stopped working for about a week during Christmas vacation. The volume up button appeared to bring up the control-alt-delete screen. I could control the volume of individual programs in the volume control panel, but nothing would make the master volume work. I contacted support via chat. They eventually called, and then hung up on me. I brought the unit into a Microsoft Store where the problem went away when I booted the machine. They had no insight; and the problem never came back.
  • No Internet: In the middle of February, I lost all Internet access. No wifi and no wired connection through the dock. I could access file shares on the network, and could ping IP address but I appeared to have no DNS lookups. It was bizarre. I found a solution here. Basically, I had to deactivate IP6 in Network adapter settings; reboot the machine, then reactivate IP6. I spent a half day on this.
  • A Blank Surface Book Screen: The day I was writing this article, my Surface Book screen went blank. I had left the computer for a bit and came back to find the issue. Thankfully, this is a known issue, and the fix is to press the windows key + control + shift + B at the same time. I understand this is a hotkey for resetting the display driver. I've only had this scenario happen twice; but I've seen a lot of complaints about it.

Open Issues

Here are some open issues with my Surface Book setup:

  • Random Crashes or Reboots: Sometimes I leave my computer on when I go out to lunch. When I come back and sign in, it is as if the computer is being booted up for the first time today. None of the programs I left running are running. I have no explanation for why this happens. It is sporadic.
  • No External Monitor: When I come back to my desk after lunch, nothing will display on my external monitor. The computer seems to think the monitor is there; but the monitor is blank. Trying to disable the monitor, or re-enable it in display settings gives an error. This started after the last Windows update. I found a solution, but it is tedious.

    1. First unplugged the external monitor from the dock.
    2. Then unplug the dock from the computer.
    3. Then plug the external monitor into the Surface Book. This resets and the secondary monitor displays properly.
    4. Now unplug the secondary monitor from the computer and plug it into the dock
    5. Finally, reconnect the dock to the computer.

    Just like magic you'll have a working external monitor again. I wish the Windows Key + Control + Shift + B command worked here, but it doesn't.

  • Clipboard Detached when it isn't: The Surface Book perpetually thinks the Clipboard is not attached even when it is. This error started after the last firmware update. Sometimes a reboot will help. Sometimes a reboot into the EUFI screen will help. Do this by pressing the volume up button at the Surface while the Surface Logo appears on the screen. After that simply exit the EUFI screen. Neither of these fixes are consistent. Sometimes they don't work. Sometimes the problem comes back.

One More Thing

I have no idea how this dent happened:

So, if you get one, be careful. The unit is not indestructible.

Final Thoughts

The Surface Book is an awesome, if imperfect, machine. I'm frustrated as I write this because I have more issues today than I did three weeks ago. The last two updates were not kind to me. Based on Reddit forums, people have had issues lots more serious than I. In retrospect, I could survive without the clipboard functionality; but it is a nice to have. I expect all my issues are software related and will be fixed with firmware or software updates. I bet in another six months; the Surface Book will be the perfect computer.

This whole blog post, including video and photo editing was done on the Surface Book!

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.