Check out our new training course on AngularJS for Flex Developers

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

How do I specify a startIndex when using AngularJS ngRepeat ?

TLDR: use a filter.

I was working on an app for a client and wanted to create a drop down from a controlled vocabulary. In this particular case I did not want to show the first element of the array which would populate the drop down. In an ideal world, I would just have the service guys give me a service that omitted the unnecessary elements for UI use. In this case that wasn't an option. I needed to do something to remove the elements in the UI.

I could have written code to loop over the array, and create a new array. But, instead I decided to use an AngularJS Filter.

The Problem

Let's piece together an app to demonstrate this:

First, import the Angular library:


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

Then, create an AngularJS Application:


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

This code should go in another Script block.

Then create a controller:


angular.module('testModule').controller('testController', ['$scope',function($scope){
$scope.someControlledVocabulary = [
{id:0,label:'Don\'t Show This One'},
{id:1,label:'Value 1'},
{id:2,label:'Value 2'},
];

$scope.selectedValue = $scope.someControlledVocabulary[1].label;

}]);

The controller contains a hard coded controlled vocabulary. The $scope also contains a selectedValue that refers to the second item in the controlled vocabulary. You could default this to anything.

Now, create the view, with a select box:


<body ng-app="testModule">

<div ng-controller="testController">

<b>Drop down with no filter</b>:
<select ng-model="selectedValue">
<option ng-repeat="vo in someControlledVocabulary" value="{{vo.label}}" >{{vo.label}}</option>
</select>
<br/><br/>
<b>Selected Value</b>: {{selectedValue}}<br/><br/><br/>
</div>
</body>

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

You'll see that all the items in the controlled vocabulary are displaying in the drop down. We want to prevent that.

Create a Filter

In your JavaScript code block, create a filter. I wrote a bit about filters in the past. This is our new filter:


angular.module('testModule').filter('startAt', function(){
return function(inputArray, startAt) {
return inputArray.slice(startAt);;
};
});

The AngularJS filter is named startAt. It's value is a function that returns the filter function. The inputs are the item being filtered--in our case the controlled vocabulary array--and the item index you want to start your display at. The actual filter function uses JavaScript's slice method to create a new array with all items after the startAt value.

Modify the view where the ng-repeat loops over the options to add the Filter:


<option ng-repeat="vo in someControlledVocabulary | startAt:1" value="{{vo.label}}" >{{vo.label}}</option>

When the view is processed the code will truncate the controlledVocabulary and the first item in the drop down will be skipped:

Everything works great. You can modify the startAt value to remove more than one item from the drop down.

Play with this code on Plunkr.

Like This? Sign up for my Monthly Newsletter

Why is AngularJS removing spaces on my inputs?

An app that I'm working on needed to validate a user's text input to make sure that they did not put spaces before, or after, the actual text. The business decision was made to warn the user of the extra spaces instead of automatically trimming the data. However, when it came time to write the validation code; we found that AngularJS was automatically trimming spaces. What can we do about that?

The problem

First, let's build an app to demonstrate the problem. Load in 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 in another script block:


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

Next, create an Angular controller:


angular.module('trimTest').controller('someController',['$scope', function($scope){
$scope.value1 = " Hello ";
$scope.onValue1Change = function(){
console.log($scope.value1);
}
}]);

This controller keeps a single value in the $scope and has a single function that will execute when the view input is changed.

This is the view code:


<body ng-app="trimTest">
<div ng-controller="someController">
<input type="text" ng-model="value1" ng-change="onValue1Change()"> <Br/>
<pre>
{{value1}}!
</pre>
</div>

An HTML text input is used and the ng-model ties associates the input with the scope value, value 1. The value is output inside a pre tag; so that all spaces are shown and not truncated.

Try this app. Type in text box and you'll see that the display inside the pre doesn't change no matter how many spaces you type. Watch the console debug output for the onValue1Change() method and you'll see that typing spaces, either before, or after the text in the input does not trigger the change value.

Angular is automatically trimming spaces before performing a compare which will trigger the ngChange. I've had similar experiences when putting my validation code inside a directive. The problem is that if a user adds extra spaces before or after their text, my validation code will not execute, and therefore the user will not get feedback of their erroneous input in the UI.

The Solution

The Angular developers have planned for my problem. They added an Angular attribute to the input tagged named ngTrim. To demonstrate, we'll modify our previous application, so we can see an input with an ngTrim side by side to one without. First, add anew $scope variable inside the controller:


$scope.value2 = "World";

Also add a change function for the new input:


$scope.onValue2Change = function(){
console.log($scope.value1);
console.log($scope.value2);
}

This change function outputs both value1 and value2 from the $scope. For completeness, Modify the onValue1Change() function to do the same:


$scope.onValue1Change = function(){
console.log($scope.value1);
console.log($scope.value2);
};

Now modify the view code:


<b>Value with ngTrim not set</b>:
<input type="text" ng-model="value1" ng-change="onValue1Change()"> <br/>
<b>Value with ngTrim set to false</b>:
<input type="text" ng-model="value2" ng-trim="false" ng-change="onValue2Change()"><br/><br/>
<pre>
{{value1}}! {{value2}}!
</pre>

I added some labels to each input. The second input uses ngModel to associate itself with the value2 in the controller's $scope. The ngTrim attribute it set to true; and the ngChange will call the onValue2Change() function.

Play with this code . The second value, with the ng-trim set to false, will add spaces before or after the text as they are typed. This is immediately referenced in the view display, and you can also see it in the console output from the ngChange method.

Sign up for DotComIt's Monthly Technical Newsletter

Using Values in AngularJS

AngularJS has something they call the value recipe. Values are similar to constants, something I already wrote about. The difference between an AngularJS constant and an AngularJS value is very subtle. Constants and values are the same with the exception that a value can be injected into a configuration block and then changed before it is injected into controllers or services. Constants cannot be injected into configuration blocks.

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

Creating a Value in AngularJS

Let's create a simple app that creates an Angular value and shares it 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('valueTest',[]);

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


angular.module('valueTest').value('someStringValue','someStringValue');

The value accepts two different values. The first is the name of the value and the second is the value of the value. That sounds more confusing than it should. The syntax is similar to what you would use when creating a service, or controller, or constant. Let's create a controller that makes use of the value:


angular.module('valueTest').controller('someController',['$scope','someStringValue', function($scope,someStringValue){
$scope.someStringValue =someStringValue;
}]);

The someStringValue value is passed into controller using angular's dependency injection syntax. Then the value is copied into the $scope so it can be used in the view code. The second controller uses a similar approach:


angular.module('valueTest').controller('someController2',['$scope','someStringValue', function($scope,someStringValue){
$scope.someStringValue =someStringValue;
}]);

Let's take a look at the views:


<body ng-app="valueTest">
<div ng-controller="someController">
<b>Controller1 value</b>:{{someStringValue}}
</div>
<div ng-controller="someController2">
<b>Controller2 value</b>: {{someStringValue}}
</div>

This sample mirrors the sample I used in my article about constants. Run the app you should see something like this:

Check out the sample here.

What happens when we change the value?

When I first read about values in AngularJS I was given the impression that the difference between a value and a constant was that a value could be changed while a constant could not be changed. So, when creating this article I wanted to see what would happen if we changed the value. We can modify the view to add an input that allows us to change the value:


<div ng-controller="someController">
<b>Controller1 value</b>:{{someStringValue}}<br/>
<b>Value</b>:
<input type="text" ng-model="someStringValue" size="50"/>
</div>
<div ng-controller="someController2">
<b>Controller2 value</b>: {{someStringValue}}<br/>
<b>Value</b>:
<input type="text" ng-model="someStringValue" size="50"/>
</div>

Rerun the app and give it a shot:

Play with this app here.

The results surprised me. Changing the value inside one controller did not affect the other controller. The value is treated exactly like a constant is in this situation. There is no automatic binding or updates of the value between two controllers.

What about Object Properties?

When I wrote about constants, I wondered if the constant changes would trickle through controllers if the constant was an object instead of a value. I found that this was the case. I did the same experiment with values and found the same results.

First, create the value:


angular.module('valueTest').value('someObjectValue',{value:'someObjectValue'});

Then modify the two controllers to reference someObject value instead of someStringValue:


angular.module('valueTest').controller('someController',['$scope','someObjectValue', function($scope,someObjectValue){
$scope.someObjectValue=someObjectValue;
}]);
angular.module('valueTest').controller('someController2',['$scope','someObjectValue', function($scope,someObjectValue){
$scope.someObjectValue =someObjectValue;
}]);

Then modify the views:


<div ng-controller="someController">
<b>Controller1 value</b>:{{someObjectValue.value}}<br/>
<b>Value</b>:
<input type="text" ng-model="someObjectValue.value" size="50"/>
</div>
<div ng-controller="someController2">
<b>Controller2 value</b>: {{someObjectValue.value}}<br/>
<b>Value</b>:
<input type="text" ng-model="someObjectValue.value" size="50"/>
</div>

Test out the app:

Play with this here.

When the object's value property is modified in one controller, the change immediately propagates to the other controller. This is because the value is a link to the object; and changing properties on the object do not change the actual value.

Final Thoughts

In practical terms; Angular values are not much different than Angular constants. The real difference is that the value can be injected into an AngularJS configuration block while the constant cannot be. In the configuration block, the value could be changed before the value is injected into services or other controllers. The constant, on the other hand, cannot be injected into a configuration block; and as such cannot be changed before being injected into a service or controller.

Honestly, to me, I'm failing to see the need for constants and values. Most of the time I find myself wrapping shared values inside Angular services. Angular services are designed to be shared between controllers and when values change Angular binding handles it for us.

Tell me what I'm missing! How do you use Angular values in your application development?

Sign up for DotComIt's Monthly Technical Newsletter

How to use indexOf() function in JavaScript

I have been working on an AngularJS project for a client. During a code review I came across code that uses $.inArray(). I flagged the line saying that I prefer not to use JQuery code within an Angular controller. I also stated that a more Angular way was to use forEach() or even a vanilla JavaScript for loop.

My team member pointed out that this code wasn't processing all items in the array; just looking for one. Out of curiosity; I opened up the JQuery framework and sure enough; inArray() is implemented as a for loop in the JQuery framework. Sometimes you have to pick your battles with clients, so I let this one slide.

My second impulse was to recommend they use indexOf(). This article will talk about what indexOf() is and how it can be used.

What is indexOf()?

The indexOf() function takes the format of this:


valueToSearchIn.indexOf(valueToSearchFor, startLocation);

The important pieces are:

  • valueToSearchIn: The valueToSearchIn variable is a string or array and is the element you want to search within. You call the indexOf() function on this variable.
  • valueToSearchFor: This valueToSearchFor parameter is the first parameter to the indexOf() function. It contains the value you want to find in the valueToSearchIn element.
  • startLocation: the startLocation refers to the index you want to start searching. If left out, it is set to 0 which is the first element of your string or array.

The return value from the function will be an integer referring to the location of the first instance of the valueToSearchFor. If -1 is returned then no value was found.

Using indexOf() with a String

Let me show some examples. First, create a JavaScript string:


var str = 'This is a String';

Now, try this:


console.log(str.indexOf('i'));

What should the return value be? It should be two because if we traverse the original string, you'll see:

0 = T

1 = h

2 = i

The method finds the first instance of the lowercase i and returns true. Here are a few more samples:


console.log(str.indexOf('This')); // returns 0
console.log(str.indexOf('is')); // returns 2
console.log(str.indexOf('str')); // returns -1 because this search is case sensitive
console.log(str.indexOf('Str')); // returns 10

Using indexOf() with an Array of Simple Values

Next create a string array:


var stringArray = ['This','is','a','String','Array'];

We can test a few items:


console.log(stringArray.indexOf('i'));

The result of this will be -1 because no string value consisting of a lowercase I exists within the array. When using indexOf on an array; the two values must match identically. Even though item 0 ('This'), item 1 ('is'), and item 3 ('String') contain a lowercase I they will still not equal to the lowercase I and will return nothing.

Here are a few more comparisons:


console.log(stringArray.indexOf('This')); // returns 0
console.log(stringArray.indexOf('is')); // returns 1
console.log(stringArray.indexOf('str')); // returns -1
console.log(stringArray.indexOf('Str')); // returns -1
console.log(stringArray.indexOf('Array')); // returns 4

Using indexof with an Array of Objects

Let's see how this function works with an array of objects. First, create the object array value:


var objectArray = [{value:'This'},{value:'is'},{value:'a'},{value:'Object'},{value:'Array'}];

Now, try to look for the string with a lowercase 'I':


console.log(objectArray .indexOf('i'));

This will return -1; because the literal string containing a lowercase I will not be equal to any of the objects in the objectArray.

Now try this:


console.log(objectArray .indexOf({value:'is'}));

What do you think will happen? Even though the object we are searching for is the functional equivalent of an object in the objectArray, the result will still be -1. The indexOf() test is checking whether two objects are the same; not comparing properties inside an object. Even though the two objects seem similar to us, visually, they are not holding the same place in memory and therefore are not the same object according to the browser.

Try the compare with an object directly out of the array:


console.log(objectArray .indexOf(objectArray[3]));

This will return 3; because we checking for the third object in an array.

Try this:


var tempObject = objectArray[4];
console.log(objectArray.indexOf(tempObject));

This copies an object from the array into a local variable. When the indexOf() function searches for that object in the array it finds it, properly, and returns the index value of 4.

You can view all the samples at this plunker

Why does JQuery include a custom implementation of indexOf?

JQuery includes its own implementation of indexOf(), and that implementation is used by the inArray() method. According to the documentation, JQuery has its own implementation for performance reasons; and gives this link as proof. I ran the tests in Firefox, Edge, and Chrome. Primarily the custom indexOf() function was quicker than the native one. For the low index test; Chrome did report that the native indexOf() performed better than the custom indexOf() function. I don't perceive the differences would amount to anything calculable in a real world application--unless you are going to performing the indexOf() function in a loop.

My preference would be to use the native indexOf() function; because I think that would improve readability of the code. What do you think? Is that impulse misplaced? Should I focus more on tweaking every millisecond of performance about of JavaScript?

Sign up for DotComIt's Monthly Technical Newsletter

Using Constants in AngularJS

A constant is a value that never changes. Some examples of constants might be the speed of gravity on the earth (9.8 m/s^2), or the value of pi (3.14159...). In a software application I might use constants for the location of my remote services or file systems that the application interacts with.

AngularJS provides a way to create and use constants, and this post will tell you all about it.

Creating a Constant in AngularJS

In AngularJS, a constant is treated similar to a service or factory. The constant is created as part of the application using the constant method. It can be injected into a controller, or other service, using Angular's dependency injection syntax. This post will create a sample app that shares a constant between two separate controllers.

First, import the angular library:


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

Then, create an angular application:


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

I named the application constantTest, and there are no additional arguments passed into the module.

Next, create the constant:


angular.module('constantTest').constant('someStringConstant','someConstantValue');

The constant method is called on the module. It accepts two values; the name of the constant and the value of the constant. The value could be a simple object such as a number or string, or it could be something more complex such as another object.

Next, create a couple of controllers, each using the constant:


angular.module('constantTest').controller('someController',['$scope','someStringConstant', function($scope,someStringConstant){
$scope.someStringConstant =someStringConstant;
}]);
angular.module('constantTest').controller('someController2',['$scope','someStringConstant', function($scope,someStringConstant){
$scope.someStringConstant =someStringConstant;
}]);

Each controller uses Angular's dependency injection syntax to inject the $scope service, and our custom someStringConstant into each controller. The constant value is saved to the scope.

Once in the scope, the constant value can be output to the screen as part of a view:


<body ng-app="constantTest">
<div ng-controller="someController">
<b>Controller1 value</b>: {{someStringConstant}}
</div>
<div ng-controller="someController2">
<b>Controller2 value</b>: {{someStringConstant}}
</div>

Run this app, and you should see something like this:

Play with the sample here. This shows how to share a constant between two separate controllers. I have built the sample example in the past to demonstrate how services work.

What happens when we change the Constant?

The purpose of a constant is that it isn't supposed to change during the lifecycle of the application. What happens if we try to change the constant value as part of the application? We can experiment with that by changing the value in the first controller:


angular.module('constantTest').controller('someController',['$scope','someStringConstant', function($scope,someStringConstant){
someStringConstant = 'something else';
$scope.someStringConstant =someStringConstant;
}]);

The output should look something this:

It shows us that the value is changed within someController, but that change has no effect on someController1. In essence, the value was overwritten; but not changed.

Play with this sample here.

What happens if we try to change a constant using user input? We can modify our original sample to add an input:


<div ng-controller="someController">
<b>Controller1 value</b>: {{someStringConstant}}<br/>
<b>Constant</b>:
<input type="text" ng-model="someStringConstant" size="50"/>
</div>
<div ng-controller="someController2">
<b>Controller2 value</b>: {{someStringConstant}}<br/>
<b>Constant</b>:
<input type="text" ng-model="someStringConstant" size="50"/>
</div>

The controllers remain unchanged in this case. Try this app and try to change the constant values by tying into the text inputs between the two controllers:

You'll see that as you type in one; the controller's local value is overwritten, but the constant value in the other controller is unaffected. If we were using a service to store this value, all the values would be synced through Angular's data binding. With a constant, only the controller changing the constant will see the new value.

Play with the sample here.

What about object properties?

In JavaScript, inheritance is done through something called prototypes. That means new objects are created by making a copy of an existing object. This often means that object properties are often inherited. When creating Angular directives, wrapping simple parameters inside an object is a way to avoid scoping issues that don't give you access to the data. Because of this, I wondered if an object constant would be handled differently than the string constant we used in previous samples. Will changing a property on the constant object affect the property in other controllers?

First, change the constant:


angular.module('constantTest').constant('someObjectConstant',{value:'someConstantValue'})

Instead of a simple value, the constant's value is now an object. I also changed the name of the constant from someStringConstant to someObjectConstant.

Modify the controllers to reference the new constant:


angular.module('constantTest').controller('someController',['$scope','someObjectConstant', function($scope,someObjectConstant){
$scope.someObjectConstant =someObjectConstant;
}]);
angular.module('constantTest').controller('someController2',['$scope','someObjectConstant', function($scope,someObjectConstant){
$scope.someObjectConstant =someObjectConstant;
}]);

These controllers, save the object value into the $scope.

The view code mimics one of our previous examples:


<div ng-controller="someController">
<b>Controller1 value</b>: {{someObjectConstant.value}}<br/>
<b>Constant</b>:
<input type="text" ng-model="someObjectConstant.value" size="50"/>
</div>
<div ng-controller="someController2"
<b>Controller2 value</b>: {{someObjectConstant.value}}<br/>
<b>Constant</b>:
<input type="text" ng-model="someObjectConstant.value" size="50"/>
</div>

Run this code and you'll see that all the items change in sync with each other.

Play with the sample here.

I believe this is because the constant value in this case is a pointer to the object; and changing properties on the object does not actually change the constant value; so the changes are immediately updated.

Final Thoughts

Since the value can be changed, or overwritten, defeats the purpose of using a constant in the first place. This seems to be syntactical sugar within the limits of the JavaScript language, which doesn't provide support for true constants. On one hand this defeats the purpose of using a constant; which is to provide immutable values throughout your code. On the other hand it does give a clear signal of intent to other developers on your team.

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.