Check out our new training course on AngularJS for Flex Developers

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!

How do I Copy to the Clipboard with JavaScript?

Copying something to the clipboard is one area where ActionScript has traditionally been superior to JavaScript and HTML. For the longest time there was no way to easily copy something to the clipboard from JavaScript and have it work in all browsers. Even sites like Github have traditionally relied on a hidden swf in the background to copy their repo URLs into the clipboard. As browsers, progress, this starts to change. I found a great JavaScript library, clipboardjs that gives us copy to clipboard functionality without the use of Flash.

Using ClipboardJS to Copy

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 page elements where the class was named 'btn'. On said elements, the library will look for special attributes that tell the library how to operate.

First, we need an input that can be copied:


<input id="input" value="Some Text">

This input contains the target text that we want to copy.

Next, we need a button to perform the copy:


<button class="btn" data-clipboard-target="#input">Copy</button>

This button uses the class btn; which is the name of the class we used when initializing the Clipboard object. The clipboard object looks for the data-clipboard-target attribute; and uses that value to find the target text to copy.

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

Test this out.

Using ClipboardJS to Cut

ClipboardJS can also be used for performing cut operations. You just need to add one additional data attribute to the trigger element:


<button class="btn" data-clipboard-action="cut" data-clipboard-target="#input">Cut</button>

The data-clipboard-action is specified. The default is copy, however in this case we set it to cut. The text in the input will copy it into the clipboard and remove it from the relevant input.

Test this out.

Sign up for DotComIt's Monthly Technical Newsletter

How do I remove a property from an object in JavaScript?

Programmers specialize their knowledge. They learn some things extremely well, but often have limited experience beyond that. It makes sense, because you learn enough to solve the problem at hand then stop looking for an answer.

I'm no different! Even some languages, like JavaScript have aspects I never learned. This post is about one of those aspects.

I was working on on an Angular app for a client and added a 'reset' function to many of our shared data models. When the user logged out, we wanted to make sure that no data was in memory from that user's session. My initial approach was to reset all the values back to a defaults value. Arrays went back to empty arrays; numbers went to 0 or -1; a strings went back to empty strings. One of my colleagues suggested that instead of defaulting the values; we could delete them from the service object.

"Huh, I said? How do you do that?"

Use the delete operator.

How do use the Delete Operator

The delete operator will remove a property from an object. I put together a simple sample to demonstrate this.

First, create an object:


myObject = {
value1 : 'Foo',
value2 : 'Bar'
};

This snippet creates an object named myObject with two properties on it.

Next output the object, so you can see what it is:


console.log(myObject);

Then run the delete command to remove one of the object's properties:


delete myObject.value1;

The delete command starts with the delete operator, followed by a space. After that specify the object and property where you want items to be removed. Object property notation is used; so a dot separates the object variable and its property.

Next, output the object again:


console.log(myObject);

Int he two logs you'll see that the value1 property is part of the object in the first log; and removed from second log.

I'm amazed I've never run into that operator before.

Play with a sample here.

Sign up for DotComIt's Monthly Technical Newsletter

Using Angular to Open a Link in a New Window with a Button click

I was recently working on a client app and had to open a link in a new window. This is easy to do with an anchor, because you can specify the target. When you're dealing with a HTML button that answer was not as obvious.

How does one use Angular to open a link in a new window on a button click? The answer is to use the JavaScript open method and Angular's $window service.

Let's create a sample app. First, load in the Angular framework:


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

Then create an Angular Module:


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

Next, create an Angular controller:


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

Angular injects two services into the controller for this sample: the $scope service and the $window service. The $scope service is used to share data between the view and the controller. The $window service is an Angular service representing a reference to the current window object.

Now create an open window function:


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

We can call the open() function directly on the angular $window service and it will do what we want.

Next we need a button that will trigger this function:


<body ng-app="openWindowTest">
<div ng-controller="controller1">
<button ng-click="openWindow()">Open Window</button>
</div>
</body>

The Angular module is attached to the body tag using the ngApp directive. The controller is attached to the div using the ngController directive. The button uses the ngClick directive to call the open window method.

Try it, and you'll see my blog opens in a new window, or tab, depending on your browser. This is one of the simpler JavaScript tasks I've had to tackle this week.

Sign up for DotComIt's Monthly Technical Newsletter

How can I avoid Cross Domain Restrictions When doing HTML5 Development?

Sometimes when I'm developing an HTML5 app for a client it does not make sense to set up the client's full environment on my local machine.

Sometimes the setup is complicated and the budget doesn't allow me to spend a day or two for setup. Sometimes the apps are leveraging services that spread between multiple departments and servers and it is not practical to set them all up locally. Other times, the client wants me up and running in the shortest order possible. In such situations, I still write code on my local local machine, but access their services remotely.

HTML applications that run in a browser this can cause a problem. The HTML app can't use xmlHTTPRequest to make calls to remote servers. This is done to prevent normal users from running into cross site scripting which are often used for nefarious means.

When developing code locally, however, my use is legit and I need a temporary work around. In these situations, I often go to a a Chrome command line argument that disables cross site scripting restrictions:


pathtoChromeInstall\Chrome.exe -disable-web-security

Once this is in place, I am able to run HTML code on my local server that can make remote service calls to my client's server. Then all is good in the world and I'm able to continue to work productively with my client.

There is a great StackOverflow writeup on this point.

Comparing AngularJS Providers, Factories, Services, Constants, Values, and Decorators

This post is is designed as a reference cheat sheet. I've written about Providers, Factories, Services, Constants, Values, and Decorators in more detail in past posts. This is a simple table intended to compare them. I had something similar in the bonus materials of my AngularJS training course; but it didn't include Constants, Values, or Decorators.

Element Singleton Instantiable Configurable Comment
Provider Yes Yes Yes
  • A Configurable Factory.
  • The code behind both the Service, Factory, Value, Constant, and Decorator.
  • Available during the configuration phase.
  • Can be intercepted by decorator.
Factory Yes Yes No
  • A Injectable function.
  • Returns an Object
  • Easy to pass arguments to a constructor since you create your own object.
  • Can be intercepted by decorator.
Service Yes No No
  • A Simple Injectable Constructor.
  • Uses the new keyword to create an object.
  • Returns an instance of the object.
  • Can be intercepted by decorator.
Value Yes No No
  • A Simple injectible value.
  • Can not be injected into config blocks.
  • Can be intercepted by decorator.
Constant Yes No No
  • Cannot be intercepted by a decorator.
  • It is possible to change this value programmatically.
Decorator Yes No No
  • Used to modify other elements in this list, except constants.
  • Can be intercepted by another decorator.

Sign up for DotComIt's Monthly Technical Newsletter

Using Decorators in AngularJS

A decorator is a design pattern. A decorator is, basically, a wrapper for an object. It doesn't change the API of that object, but does change the functionality.

One use for decorators might be to add authentication code to a services API. The authentication code could be encapsulated and use for all service calls; but doesn't inherently change the functionality of a single method. Decorators can be used for caching purposes in a similar manner.

There is a decorator method implemented as part of the AngularJS library. It allows you to use a decorator to modify an Angular service, factory, provider, or value. This feature was added in Angular 1.4, before I wrote my AngularJS training course. This article will tell you how to use a decorator in the context of an AngularJS Application.

Creating a Simple Angular Application

The first step in any AngularJS application is to import the angular framework:


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

Then, create a module:


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

The module should be put in a script block, in case that wasn't obvious.

Next, create a service:


angular.module('decoratorTest').service('myService', function(){
return {
value : "Value in Service"
}
});

The service is named myService; and the service object contains a single property, named value.

Next, create a controller. The controller will add the myService to the $scope so the value can be displayed within a view:


angular.module('decoratorTest').controller('controller1',['$scope','myService',
function($scope,myService){
$scope.myService = myService;
}]);

The controller's name is controller1. It has two services injected into it: Angular's $scope service and our custom myService. Create a view to output the data:


<body ng-app="decoratorTest">
<div ng-controller="controller1">
<b>Service in Controller 1</b>: {{myService.value}}
</div>
</body>

The decoratorTest module is added to the body tag using the ngApp directive. The controller1 controller is put on a div with the ngController tag. The service value is output. You should see something like this:

This a simple app that simply displays some data from the controller in the view. It does not yet use a decorator.

Using a Decorator

Now let's add a decorator to the app. This decorator will change the value constant instead the service. AngularJS defines a decorator using a method off the main module. This is the generic format:


AngularJSModule.decorator(ServiceTobeModified, ['$delegate',function($delegate){
return {
// modified service
}
}

The decorator function is called on the module. It accepts two arguments. The first argument is a string that refers to the service, or factory, or provider, or value to be modified. The second argument is the modifier function. In this case, we are injecting a single item into the decorator and that is the service function to be modified. The $delegate argument is injected to the decorator function using standard AngularJS dependency injection syntax. It represents the service as is, without any modifications.

For the purposes of this sample, we are going to modify the value on the service to say 'decorated' after the original value. This would be our modified code:


angular.module('decoratorTest').decorator('myService',['$delegate', function($delegate){
return {
value : $delegate.value + " decorated"
}
}]);

Run your updated app and you should see something like this:

Play with the code

Final Thoughts

Technically we could create decorator like functionality using providers and an Angular config. But, using the decorator function is a much easier approach. It also allows us to add decorators to our app at any point, not just at the config stage. Decorators can be used for much more advanced purposes than this sample. We could add new functionality or values to our service.

I find decorators are most useful when dealing with third party services that I want to use almost as is, but make minimal changes. Have you been using them? What for?

Sign up for DotComIt's Monthly Technical Newsletter

Understanding the AngularJS Provider

A Provider in AngularJS is the root of many other Angular constructs. Constants, values, services, and factories are all helper functions that use a provider under the hood. For situations where you need the most control; a Provider is the way to go. When using providers; you create an object with a function named $get. When the provider is first initialized; the $get function is executed and the results will be returned to the provider. The provider approach allows for advanced configuration options because you can modify the object in a config block before the provider object is created.

This article will give you some samples of using a provider in an AngularJS application.

Creating a Provider in AngularJS

Let's create a simple app that creates an Angular provider and uses it to share data between two separate controllers. First, load the angular library:


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

Then, create an angular module:


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

The next step is to create the provider. This is done using the provider function on the angular module:


angular.module('providerTest').provider('myProvider', function(){
this.$get = function(){
return {
value : "Value in Provider"
};
}
});

The provider method accepts two values. The first is the name of the provider, which will be referenced by Angular when injecting the provider into a controller. The second argument is a function. The function must contain a $get method defined within. The $get method will be executed to return the provider object. I created a simple provider object that contains a single simple value. The provider object is a standard JavaScript object and can contain properties, variables, and functions. In this case the provider is named myProvider. In AngularJS a provider creates a Singleton object, meaning only a single version of this object will be created. The first time the object is referenced the $get function will be executed and Angular will save a copy of the resulting object. Subsequent references of the provider will return the same object.

Let's create a couple of controllers that use the service:


angular.module('providerTest').controller('controller1',['$scope','myProvider',
function($scope,myProvider){
$scope.myProvider = myProvider;
}]);
angular.module('providerTest').controller('controller2',['$scope','myProvider',
function($scope,myProvider){
$scope.myProvider = myProvider;
}]);

The controller function accepts two arguments. The $scope is a built in Angular service used for sharing data between a view and controller. The myProvider value is a reference to custom provider created for this sample. Inside the controller, the provider object is copied into the $scope so the data can manipulate within the view. The two controllers are almost identical.

Let's take a look at the views:


<body ng-app="providerTest">
<div ng-controller="controller1">
<b>Provider from Controller 1</b>: {{myProvider.value}}
</div>
<div ng-controller="controller2">
<b>Provider from Controller 2</b>: {{myProvider.value}}
</div>
</body>

The Angular Module is placed on the body tag using the ngApp directive. Each controller is attached to a div with the ngController directive. Inside each view; the value from the provider is displayed. Run the app and you should see something like this:

Try out this sample.

Intercepting and Changing a Provider

A benefit of a provider object is that you can intercept and modify it within an AngularJS configuration block. This is great if you want to use a single provider across multiple applications. It will give your consumers the ability to tweak the provider without having to complete rewrite it. One example of this may be to set an API key for access to remote services. Many people can share the provider object which integrates with the remote services simply by using an Angular config to change the API key. First, change the implementation of the provider:


angular.module('providerTest').provider('myProvider', function(){
var someValue = "Nothing initialized";
this.setSomeValue = function(value){
someValue = value;
};
this.$get = function(){
return {
value : someValue
};
}
});

The definition of the provider is similar; however the contents of the provider function have changed. A local value named someValue is added. I defaulted this to the text "nothing initialized". Then I added a function named setSomeValue. The function is put in the this scope of the provider function, meaning it can be accessed if you have an instance of the function. Finally the $get function specifies the provider object's value property with the value of someValue. If you run the code as is, you should see something like this:

However, the reason for this expanded provider is that we can intercept it in an Angular config block and modify the function object before the $get function is executed:


angular.module('providerTest').config(["myProviderProvider",function(myProviderProvider){
myProviderProvider.setSomeValue('initialized value');
}]);

The config function looks for myProviderProvider; which is Angular terminology to reference the function with the $get method that will eventually create the provider object. Inside the config block the setSomeValue function is executed, which changes the someValue inside the provider and will in turn change the value before the myProvider object is created and passed into the controllers.

Run the updated code:

Play with the code here

What happens when we change the value?

An important use case for a Provider (or service or factory) is that when a value is changed it is automatically updated to all views and controllers that use the value. Let's add some code to demonstrate that:


<div ng-controller="controller1">
<input type="text" ng-model="myProvider.value"/><br/>
<b>Provider from Controller 1</b>: {{myProvider.value}}
</div>
<div ng-controller="controller2">
<input type="text" ng-model="myProvider.value"/><br/>
<b>Provider from Controller 2</b>: {{myProvider.value}}
</div>

Rerun the app and type in either of the inputs. You'll see changes are automatically updated between both views:

Play with this app here

Final Thoughts

Under the hood; an AngularJS Provider provides the implementation of constants, values, services, and factories. However, in practice, I rarely need providers. The implementation of a service is simpler for most practical needs, and most times I would rely on that.

What do you think?

Sign up for DotComIt's Monthly Technical Newsletter

Using AngularJS Factories

A Factory is the name for a design pattern in which one object is used to create other objects. One of the AngularJS Recipes is named the Factory recipe. For practical purposes, a factory in AngularJS is not much different than a service in AngularJS. They are both used to share data between controllers.

This article will demonstrate how to use a factory within an AngularJS application.

Creating a Factory in AngularJS

Let's create a simple app that creates an Angular service and uses it to share data between two separate controllers. First, load the angular library:


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

Then, create an angular module:


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

The next step is to create the value. This is done using the service function on the angular module:


angular.module('factoryTest').factory('myFactory', function(){
return {
value : "Value in Factory"
};
});

The factory method accepts two values. The first is the name of the factory, which will be referenced by Angular when injecting the factory into a controller. The second argument is the function which returns the factory object. The factory object is a standard JavaScript object and can contain properties, variables, and functions. In this case the factory is named myFactory and the factory object contains a single simple property, named value. In AngularJS a factory creates a Singleton object, meaning only a single version of this object will be created. Every time it is referenced the same object will be returned.

Let's create a couple of controllers that use the service:


angular.module('factoryTest').controller('controller1',['$scope','myFactory',
function($scope,myFactory){
$scope.myFactory = myFactory;
}]);
angular.module('factoryTest').controller('controller2',['$scope','myFactory',
function($scope,myFactory){
$scope.myFactory = myFactory;
}]);

The controller function uses two arguments. The $scope is a built in Angular service used for sharing data between a view and controller. The myFactory value is a reference to custom factory created for this sample. Inside the controller, the factory object is copied into the $scope so the data can manipulate within the view. The two controllers are almost identical.

Let's take a look at the views:


<body ng-app="factoryTest">
<div ng-controller="controller1">
<b>Factory from Controller 1</b>: {{myFactory.value}}
</div>
<div ng-controller="controller2">
<b>Factory from Controller 2</b>: {{myFactory.value}}
</div>
</body>

The Angular Module is placed on the body tag using the ngApp directive. Each controller is attached to a div with the ngController directive. Inside each view; the factories value is displayed. Run the app and you should see something like this:

Try out this sample here.

What happens when we change the value?

Angular Factories operate just like Angular Services under the hood. When you change a value on the factory, it is automatically updated elsewhere. Let's add some input that allows us to change the value:


<div ng-controller="controller1">
<input type="text" ng-model="myFactory.value"/><br/>
<b>Factory from Controller 1</b>: {{myFactory.value}}
</div>
<div ng-controller="controller2">
<input type="text" ng-model="myFactory.value"/><br/>
<b>Factory from Controller 2</b>: {{myFactory.value}}
</div>

Rerun the app and type in either of the checkboxes. You'll see changes are automatically updated between both views:

Play with this app here

What Happens if I Copy a Factory's Object Properties into the $scope?

There is a mistake I made too many times admit; so I wanted to write about it here. When you copy the factory into the $scope, as we did previously, Angular binding automatically updates values. But, if you copy a factory's property directly into the $scope; the value is not updated. Let's put together a sample demonstrating a situation where Factory properties are not bound and automatically updated.

First modify the two controllers:


angular.module('factoryTest').controller('controller1',['$scope','myFactory',
function($scope,myFactory){
$scope.factoryValue = myFactory.value;
}]);
angular.module('factoryTest').controller('controller2',['$scope','myFactory',
function($scope,myFactory){
$scope.factoryValue = myFactory.value;
}]);

Previously, we copied the full factory object into the $scope. In this case only the value on the object is copied. Modify the views to reference the new $scope value:


<div ng-controller="controller1">
<input type="text" ng-model="factoryValue"/><br/>
<b>Factory from Controller 1</b>: {{factoryValue}}
</div>
<div ng-controller="controller2">
<input type="text" ng-model="factoryValue"/><br/>
<b>Factory from Controller 2</b>: {{factoryValue}}
</div>

Now test it out:

When the value is changed within the first controller's view it is not updated in the second controller. Simple values are not updated, but object values are.

Play with this sample here

Final Thoughts

Under the hood; an AngularJS Factory is one layer of abstraction removed from an Angular Service. The method for creating a service, actually calls the factory method. A service will create a new instance of the object using the new keyword while a factory does not use the new keyword when creating the factory object. For practical purposes, when building apps, this detail probably doesn't matter.

Sign up for DotComIt's Monthly Technical Newsletter

Using AngularJS Services

The most common approach I use for sharing data between two AngularJS controllers is a service. An AngularJS service is a UI mechanism, and for the purposes of this article I am not referring to remote REST services that populate your application with data. I am talking about facilities that AngularJS provides to share data between different views and controllers.

This article will demonstrate how to use a service within an AngularJS application.

Creating a Service in AngularJS

Let's create a simple app that creates an Angular service and uses it to share data between two separate controllers. First, load the angular library:


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

Then, create an angular module:


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

The next step is to create the value. This is done using the service function on the angular module:


angular.module('serviceTest').service('myService', function(){
return {
value : "Service Value"
}
});;

The service method accepts two values. The first is the name of the service and the second is a function which returns the service object. The service object is just like any JavaScript object and can contain functions or properties or variables. In this case the service is named myService and the service object contains a single property, named value. In AngularJS a service is a Singleton object, meaning only a single version of this object will be created.

Let's create a couple of controllers that use the service:


angular.module('serviceTest').controller('controller1',['$scope','myService',
function($scope,myService){
$scope.myService = myService;
}]);
angular.module('serviceTest').controller('controller2',['$scope','myService',
function($scope,myService){
$scope.myService = myService;
}]);

The controller function accepts two separate arguments, the $scope and the myService. The $scope is a built in Angular Service that helps share data between the view and controller. The myService is our custom service which helps share data between our two controllers. The service object is copied into the $scope so we can manipulate its' properties inside the view. The two controllers are almost identical.

Let's take a look at the views:


<body ng-app="serviceTest">
<div ng-controller="controller1">
<b>Service in Controller 1</b>: {{myService.value}}
</div>
<div ng-controller="controller2">
<b>Service in Controller 2</b>: {{myService.value}}
</div>
</body>

The Angular Module is put on the body tag with the ngApp directive. Each controller is attached to a div. Currently the thing the controller does is display the myService's value property. Run the app and you should see something like this:

Try out this sample here.

What happens when we change the value?

A big benefit to Angular services is that when you change a service value, it is automatically updated elsewhere. Let's add some input that allows us to change the value:


<div ng-controller="controller1">
<input type="text" ng-model="myService.value"/><br/>
<b>Service in Controller 1</b>: {{myService.value}}
</div>
<div ng-controller="controller2">
<input type="text" ng-model="myService.value"/><br/>
<b>Service in Controller 2</b>: {{myService.value}}
</div>

Rerun the app and give it a shot:

Play with this app here.

What Happens if I Copy Service Object Properties into the $scope?

When writing up this article, I Wondered what would happen if we copied the service value into the $scope instead of the whole service. Would values still change? Let's find out!

First modify the two controllers:


angular.module('serviceTest').controller('controller1',['$scope','myService',
function($scope,myService){
$scope.myServiceValue = myService.value;
}]);
angular.module('serviceTest').controller('controller2',['$scope','myService',
function($scope,myService){
$scope.myServiceValue = myService.value;
}]);

Instead of the service object being copied into the $scope; now the value on the object is copied to the scope. Modify the views to reference the new $scope value:


<div ng-controller="controller1">
<input type="text" ng-model="myServiceValue"/><br/>
<b>Service Value in Controller 1</b>: {{myServiceValue}}
</div>
<div ng-controller="controller2">
<input type="text" ng-model="myServiceValue"/><br/>
<b>Service Value in Controller 2</b>: {{myServiceValue}}
</div>

Now test it out:

When the value is changed within a controller's view it is not updated to the other controller. I ran into similar functionality when dealing with values and constants. Simple values are not updated, but object values are.

Play with this sample here

Final Thoughts

Angular Services are my goto mechanism for sharing data within Angular applications. They seem the simplest to use and implement inside an application and are very flexible.

Sign up for DotComIt's Monthly Technical Newsletter

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.