Check out our new training course on AngularJS for Flex Developers

How do you add an identity to an existing column in SQL Server?

I was helping a client change to a new web host. During this process I discovered an Access database was powering part of their web site. This had to go!

I imported the database into SQL Server. Unfortunately, this process removed the identify specifications on the primary key column for one of the tables. This means that the primary key column would not automatically fill in with an automatically incrementing integer. I opened up the table design, and tried to change the field back to an ID. Unfortunately, SQL Server does not allow you to add an identity specification to an existing column on an existing table.

How do I fix that?

What is the Process?

The process was tricky to figure out, but not all that too hard. Basically, do this:

  1. Create a new table with all the same columns as the old table. Make sure this new table has an identity column.
  2. Enable Identity Insert on the new table.
  3. Copy all data from the first table into the new table.
  4. Disable Identity Insert on the new table.
  5. Delete the original table.
  6. Rename the new table to the original table's name.

Then you're done.

What is the Code?

This whole process can be done quickly with a SQL Server script.

First, create the new table:


CREATE TABLE dbo.newtable_temp
(
Id int NOT NULL IDENTITY(1, 1),
textField nvarchar(100) NULL,
bitField bit not NULL
/* other fields */
)
ON [PRIMARY]
go

Then enable the identity insert:


SET IDENTITY_INSERT dbo. newtable_temp ON
Go

Next, use this script to insert all the rows from the original table into the new table:


IF EXISTS ( SELECT *
FROM dbo.newtable )
INSERT INTO dbo. newtable _temp ( Id, textField, bitField /* other fields */)
SELECT Id, textField, bitField /* other fields */
FROM dbo. newtable TABLOCKX
go

Then turn off the identity insert:


SET IDENTITY_INSERT dbo.newtable_temp ON
Go

Delete the original table:


DROP TABLE dbo.newtable
Go

Finally rename the old table:


Exec sp_rename 'newtable_temp', 'newtable'

And you should be good to go!

Much thanks to this Stack Overflow question for helping me out.

Why does my Angular $scope.$on() event Listener run twice?

I was working with a client on an app; and had to communicate between two different controllers. When something happened in one controller--the main app--I wanted to update the view in the main navigation. You can use Angular's $broadcast() to dispatch an event and $on to execute an event listener. The problem is; my event listener was executing twice. Why was this?

TLDR: There were two instance of the controller.

The App Architecture

I'm going to explain the app architecture. The app had a navigation section and a footer section, both were always displayed to the user. Between those two sections on the page were section for the main content. This was populated using an Angular router based on the URL. For the purposes of this sample, I'll just create a single simple view. The page will look like this:

  • Header
  • Main Content
  • Footer

Let's create the app outline. First, import the Angular library:


<script src="//code.angularjs.org/1.5.6/angular.min.js"></script>

This is often the first thing to do in any Angular applications. Now create the Angular app:


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

Create a controller for the navigation and the main content:


angular.module('sampleApp').controller('navigation',['$scope', function($scope){
}]);

angular.module('sampleApp').controller('mainContent',['$scope','$rootScope', function($scope,$rootScope){
}]);

The navigation controller accepts the $scope service as an argument. The mainContent controller accepts both the $scope and the $rootScope as arguments.

The view looks like this:


<body ng-app="sampleApp">

<div ng-controller="navigation">
</div>

<div ng-controller="mainContent">
</div>

<div ng-controller="navigation">
</div>

Notice here that the footer and the header use the same controller. That was the root of my confusion; and the reason the event listener in the navigation was dispatched twice. Don't do that.

Populate the App

I'm going to give this app skeleton enough code to demonstrate the problem. First, in the mainContent controller:


$scope.someValue = '';
$scope.onButtonClick = function(){
$rootScope.$broadcast('somethingHappened',{value : $scope.someValue});
};

I created a single #scope variable named someValue; and a single $scope function, onButtonClick(). The $scope function will execute in response to a button click, and will use the $broadcast() function on the $rootScope to dispatch an event.. Here is the mainContent view code:


<input type="text" ng-model="someValue">
<button ng-click="onButtonClick()">Do Something</button>

Enter some text in the input, click the button, and that will execute the onButtonClick() function in the mainContent Controller.

So, far so good. No create an event listener inside the navigation controller:


$scope.savedValue = '';
$scope.$on('somethingHappened', function(event, args){
$scope.savedValue = args.value;
});

The navigation controller includes a single $scope variable, named savedValue. It uses the $on() function to listen to the 'somethingHappened' event. The function takes the value dispatched as part of the event and copies it into $scope.savedValue; which in turn updates the navigation view. This is the navigation view code:


Saved Value displayed in Nav Div: {{savedValue}}<br/>

Run this App and play with the code.

It took me some head-scratching to figure out why the $on() in the navigation controller was executing. I didn't realize the same controller was used in both the footer and header. Two instances of the controller means two event listeners, which means the method gets executed twice.

In my case it was easy to discover; but if you are using Angular Routes; or any code that dynamically associates views and controllers, the second instance of the view may not be obvious. Using the same controller code for two different views is a technically valid Angular approach, but in practice I prefer not to use a controller with multiple views.

Why doesn’t ngChange fire when using ngPattern?

I was working on an app for a client recently. This app had a form, and when the user typed in one of the text inputs; I wanted to fire off an ngChange function to run some validation code. However, the ngChange was not firing consistently. It turned out to be a conflict with ngPattern. This post will explain the problem, and how to solve it.

Simple Sample

First step, I'm going to start with a simple sample demonstrating ngChange on a text Input. First, import the angular library:


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

Next, create an angular module:


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

Every angular module needs at least one controller:


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

The controller, someController, is created as part of the ngChangeTest module. It uses Angular's dependency injection syntax to pass the $scope service into the controller function. $scope is an easy way to share data and functions between a view and a controller.

Inside the controller, create a single variable and a single function:


$scope.inputText = '';
$scope.onTextChange = function(){
console.log($scope.inputText);
};

The inputText will be used with the ngModel of the textInput which we'll create in the view. The onTextChange() function will be executed when the ngChange event is fired in the view.

This is the HTML view code:


<body ng-app="ngChangeTest">
<div ng-controller="someController">
<input type="text" ng-model="inputText" ng-change="onTextChange()"> <Br/>
</div>

The ngChangeTest module is put on the body tag with the ngApp directive. The controller is added to a div. Inside the div is a text input. ngModel is associated with the $scope variable, inputText. And ngChange is associated with the onTextChange() function.

Try this out:

This works as I would have expected. For every keypress, the onTextChange() event is fired.

The problem with ngPattern

Once you introduce ngPattern into things get a bit more complicated. I'm going to use a regular expression that only accepts lowercase letters. Modify the HTML view to add the ngPattern directive on the input:


<input type="text" ng-model="inputText" ng-change="onTextChange()" ng-pattern="/^[a-z]+$/" >

The ngPattern directive does not modify the input and restrict what the user can enter into the input. It is just a regex used for validating the attribute. I was using this in a client's app which was using Angular form controls to determine whether an input was correct to determine whether the form could be submitted or not. The form was doing other validation in the ngChange method. However, I realized that the ngChange method was not firing consistently after the ngPattern directive was put in.

Try this out:

You can see from the console output that once I start typing uppercase letters; the ngChange function is no longer executing. By default, Angular prevents the ngModel from updating if the input does not meet the ngPattern; and then the ngChange does not execute if the ngModel is not updated. That was the problem I wanted to fix.

Adding in ng-options

We can tell Angular to always update the ngModel by using ngModelOptions:


<input type="text" ng-model="inputText" ng-change="onTextChange()" ng-pattern="/^[a-z]+$/" ng-model-options="{allowInvalid:true}">

The ngModelOptions directive allows us to tweak how Angular interacts with the ngModel. It is an object which contains a list of options and their values. In this case, we only need to change a single property on the options object. Set the allowInvalid to true. This means that Angular will change the ngModel even if the value is not valid according to the ngPattern. The result of this is that the ngChange function will execute regardless of the correctness of the user's input.

Play with this:

Final Thoughts

Sometimes Angular seems like a big block of unknown. There are many different ways to build angular applications and many different faucets that do not seem to be well documented, especially for changes that happen between versions. Finding these little gems is always a treasure.

Make a two column layout in Bootstrap

Multi-column layouts are a common requirement when building building HTML web sites or applications. In the old days, we would just use an HTML table and be done with it. But, these days using CSS for layout is the preferred approach. Using HTML tables for layout is considered a bad idea. Bootstrap provides an easy way to create a two column layout.

Create the two column layout: The Old Way

If I were using HTML tables to create a two column layout, I'd do something like this:


<table style="width:100%">
<tr>
<td>Label</td>
<td><input type="text" /></td>
</tr>
<tr>
<td>Some Other Label</td>
<td><input type="text" placeaholder="second text" /></td>
</tr>
</table>

This is an HTML table with two rows, and two cells in each row. This is simple, but the HTML can get complex if you are nesting tables to get specific layouts. When I started building HTML sites; this was the defacto standard for complex layouts.

Play with this sample!

Nowdays, CSS is considered superior for layout purposes than using lots of nested tables, and Bootstrap is a great framework to help you do that.

Import Bootstrap

The first step is to import the Bootstrap library into your HTML page. Bootstrap is primarily a CSS library, but also has a JavaScript portion. For the purposes of this article, we just need the CSS:


<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" >

Now all of the Bootstrap CSS is available to our application.

The Bootstrap Grid System

Bootstrap includes styles for a grid system consisting of rows and up to 12 columns. These are the associated styles:

  • row
  • Col-md-1
  • Col-md-2
  • Col-md-3
  • Col-md-4
  • Col-md-5
  • Col-md-6
  • Col-md-7
  • Col-md-8
  • Col-md-9
  • Col-md-10
  • Col-md-11
  • Col-md-12

The first style, row, is used to dictate a row in the grid. Inside the row; you would use some combination of the column styles to dictate the length of your cell; across a 12 column row. The col-md-1 style would span across a single column. The col-md-6 style would span across 6 columns. The col-md-12 style would spread across 12 columns, or a whole row. When putting together layouts with this approach, I like to make sure the total number of cells matches 12 for each row.

Create the two column layout: With Bootstrap

Bootstrap styles can be used to create a similar layout to the one created earlier, with a table. First, create the Bootstrap row:


<div id="row">
</div>

Inside the row, we can create two separate columns. For the purposes of this article, both will use col-md-6, meaning each column will span 6 cells, totaling 12 cells:


<div class="col-md-6">
Label
</div>
<div class="col-md-6">
<input type="text" />
</div>

The reason for making sure that the total number of columns used is equal to 12 is so that the next row will be placed under the first row; instead of next to it.

We can use the same approach for the second row:


<div id="row">
<div class="col-md-6">
Some Other Label
</div>
<div class="col-md-6">
<input type="text" placeaholder="second text" />
</div>
</div>

Play with the code here

Final Thoughts

The Bootstrap Grid system can be very powerful, especially when dealing with nested layout elements.

Button Clicks - Introduction to Angular 2 - Part 3

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

Review

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


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

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

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

Change the Template

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


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

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

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


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

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

Create the click handler

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


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

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

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

Play with the code here

Final Thoughts

I enjoyed my experiments with Angular 2 and JavaScript. Based on available documentation, I'm not sure if I'd start an application using Angular 2 yet, at least not with JavaScript. The documentation is not there enough for me to get started. Additionally, there seems to be a lack of supported UI libraries at this time, which will be a roadblock to any major application development. The wonderful UI Bootstrap library is not compatible with Angular 2 yet.

I'm cautiously optimistic about what the future holds for Angular, but it does not seem to be there yet.

Get our Intro to Angular 2 White Paper

Data Binding - Introduction to Angular 2 - Part 2

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

This section will expand the sample to add an input and demonstrate binding in an Angular 2 application.

Review the Component

To do that we only need to make changes to the AppComponent, which is the main component of the application. This is the component as we left it off:


(function(app) {
app.AppComponent =
ng.core.Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>'
})
.Class({
constructor: function() {}
});
})(window.app || (window.app = {}));

This component consists of two parts. The first is the main Component, which includes the component's selector and template. The component's selector is its name and that does not need to change for this article. The component's Class is the JavaScript behind the component. To date the class does nothing.

Change the Class

First, make changes to the Class. Add a helloTo variable inside the constructor:


.Class({
constructor: function() {
this.helloTo = "World"
}
})

The class parallels a controller inside of an AngularJS 1 application.

Change the Template

Next, we need to modify the template inside the component. The selector does not need to change, but we will make a lot of changes to the template. First, change the header to say hello world:


template: '<h1>Hello {{helloTo}}</h1>' +

Angular 2 uses the same view binding syntax as Angular 1 does. The plus at the end of the template is the JavaScript concatenation operator. It means we're going to add more lines. Let's start with an input:


'<input type="text" [value]="helloTo"
(input)="helloTo=$event.target.value" />
<br/>' +

The input is a standard HTML input, with the type of text. The value and the input parameters are both related to Angular. The value is enclosed in brackets. I interpret this to mean that whenever the helloTo variable changes it will also change the value of the input. This is not bidirectional. The input is surrounded by parenthesis. This is like calling a function. Whenever the input changes, the function will be executed; and the function changes the helloTo variable. The function body is defined in-line; but we could split it out into a separate function inside the component's class.

I couldn't find solid definition for the bracket or parenthesis syntax in relation to the input and AngularJS. But, my interpretation is that the parenthesis always means a method is called; and the brackets always mean a value is set. Angular 2 also includes a parallel the ngModel directive from Angular 1:


'<input type="text" [(ngModel)]="helloTo" /><br/>'

The ngModel text is enclosed in both brackets and parenthesis. Behind the scenes Angular 2 changes the helloTo class variable whenever the input changes; and the text input whenever the helloTo variable changes.

Final Thoughts

Try to run this:

As you type in one of the inputs, you'll see the other input changes as well as the hello header.

Play with the code here.

There are a few other ways you could set up the input to achieve the exact same purpose, but for the purposes of this article I decided to stop at two.

The last section of this series will focus on adding a reset button to the component.

Get our Intro to Angular 2 White Paper

Hello Angular 2 - Introduction to Angular 2 - Part 1

Angular 2 went into its first release candidate last month, but there is not a lot of information available about how to best develop applications with it. Angular is built to be used by TypeScript, JavaScript, or Dart. However, only the TypeScript tutorials are fleshed out. Coming from an Angular 1 background with JavaScript, I wanted to start my Angular 2 adventures using JavaScript.

I'm writing this series of blog posts to show how I created my first Hello World Angular 2 application using JavaScript.

Import the Angular 2 libraries

One difference I noticed between Angular 1 and Angular 2 is that Angular 2 code base is split up among many different libraries. I believe this was intentional so you could easily remove components of Angular that you do not need; thus making the overall load time for your application smaller.

Let's look at a bunch of these:


<!-- IE required polyfill -->
<script src="https://npmcdn.com/core-js/client/shim.min.js"></script>

The first is a polyfill library for Internet Explorerer. Polyfill is a term for implementing an API not natively supported. Internet Explorer requires this to support promises and dynamic modules loading, as defined as part of the ECMAScript 2015 specification. Other browsers support this by default. You can leave this out if IE is not required for your application.


<script src="https://npmcdn.com/zone.js@0.6.12?main=browser"></script>
<script src="https://npmcdn.com/reflect-metadata@0.1.3"></script>

Zone and Reflect are the Polyfills used by AngularJS.


<script src="https://npmcdn.com/rxjs@5.0.0-beta.6/bundles/Rx.umd.js"></script>

Reactive Extensions RXJS is a library for composing asynchronous and event based programs using Observable collections. Observable collections are an implementation of the Observer design pattern. It is a way for one object to notify others of state changes. Data binding is an example of this. RXJS is used in many Angular 2 applications.

Finally, import the main Angular 2 libraries:


<script src="https://npmcdn.com/@angular/core/core.umd.js"></script>
<script src="https://npmcdn.com/@angular/common/common.umd.js"></script>
<script src="https://npmcdn.com/@angular/compiler/compiler.umd.js"></script>
<script src="https://npmcdn.com/@angular/platform-browser/platform-browser.umd.js">
</script>
<script src="https://npmcdn.com/@angular/platform-browser-dynamic/platform-browser-dynamic.umd.js">
</script>

Due to the newness of the Angular 2 framework, I could not find a summary of what is contained in all the Angular libraries, nor why you'd leave them out. The official API reference contains detailed information.

Create Your First Angular 2 Component

The first thing we'll do is create an Angular 2 component. The default Angular 2 method is to wrap the component around an Immediately Invoked Function Expression (IIFE) function, like this:


(function(app) {
})(window.app || (window.app = {}));

There is no Angular code in this snippet yet, but I want to point out that a variable is passed into the function. This is window.app, which is an object. Some shorthand trickery is used to define window.app as an empty object. The code could be rewritten like this:


window.app = {};
(function(app) {
})(window.app);

I find the approach of storing a pointer to the main application object curious. Global variable are sometimes considered bad practice and when building Angular 1 applications, I went out of my way to avoid creating new ones. Here we create one for the main Angular component.

Now, let's flesh out the component:


app.AppComponent = ng.core.Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>'
})
.Class({
constructor: function() {}
});

Inside the empty app object, a property named AppComponent is created. This creates an Angular component using the ng.core.Component() function. In Angular 2 a component seems to be synonymous with a directive in Angular 1. The Component() function accepts an object as its argument. The object has two properties. The first is the selector, which is the component name and how it will be referenced in HTML code. The second is the template, which is the HTML Text. For the purposes of this sample, I defined the template inline.

After the Component() function, you'll see the dot notation used to call a second method named Class(). This is where we define the JavaScript behind the component, sort of like a Controller in Angular 1. For the moment this component has no JavaScript. It is an entity that includes some markup and some JavaScript code. Angular 2 purposely separates the JavaScript and markup portions of the template.

Bootstrap the Component

In Angular 2, you initialize an Angular application using the Bootstrap() API. This tells Angular 2 what should be the primary component for your angular application. This statement is, once again, wrapped in an IIFE:


(function(app) {
})(window.app || (window.app = {}));

The IIFE's function accepts the window.app variable, and we use the same short-hand approach to define that variable if it is not yet defined. Next, add an event listener to the DOMContentLoaded event. DOMContentLoaded is a browser event that launches whenever the page is finished loading:


document.addEventListener('DOMContentLoaded', function() {
});

Inside the DOMContentLoaded event handler function, call the bootstrap() method on the platformBrowserDynamic object:


ng.platformBrowserDynamic.bootstrap(app.AppComponent);

Now, the JavaScript behind your first Angular 2 app is ready to go. The last step is to add some HTML.

Use Component in HTML

Inside the body of the HTML application, create an instance of the my-app component:


<my-app>Loading...</my-app>

Then you're app should be ready. Try to run it, you should see the loading message:

This message should go away quickly, to be replaced by the actual app:

You can play with this code here.

Final Thoughts

This sample isn't all that interesting yet. But, in the next entries in this series I'll take a look at how to implement binding in the application and how to respond to button clicks.

Get our Intro to Angular 2 White Paper

How to fix Exceeded limit of maxWarmingSearchers=4 in ColdFusion

A new old client approached me. I hadn;t worked for them in a decade, and I suspect their code base is twice as old as that. Don;t we all love looking at old code?

The site was built with ColdFusion and used ColdFusion;s underlying search engine to search files on their site. Ten years ago, the search engine in ColdFusion was Verity and we could index sites using the cfindex tag. However, over time Verity was replaced with Solr. This inadvertently caused some issues when re-indexing their site.

The Problem

Their code to index the site was like this:


<cfindex action="update" collection="myCollection" type="file" key="someKey" urlPath="path" />

This was performed in a loop over all the new files in their site. Sometimes they did massive updates and the search indexing was failing.

The error was something like this:

Error opening new searcher.

Exceeded limit of maxWarmingSearchers=4, try again later

I set to work trying to fix it.

The Solution

If you search for this error you;ll find a lot of information about the error and Solr; but none if it is particularly useful in the context of ColdFusion. The Solr engine is getting too many indexing requests and rejecting them. It took some experimentation, but I found a solution.

First, when you;re indexing the site, add the autoCommit parameter to the tag and set it to true:


<cfindex action="update" collection="myCollection" type="file" key="someKey" urlPath="path" autocommit="true" />

This tells Solr to add the files to the search collection, but not to index them yet. After all the files have been added, perform a commit action:


<cfindex action="commit" collection="myCollection" />

Then all the files are indexed by the Solr engine at once. Discovering this was a bit tricky because the commit action is mentioned a few places in the documentation, but is not documented as a valid value for the action attribute of the cfindex tag.

After setting this up; everything worked great!

Preparing a Directive for Reuse - Building Angular Directives - Part 8

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

This post will share some things I do to prepare a directive for reuse between different angular modules. It will cover the restrict property of the directive object, and show you how to put your directive in its own module.

Be sure to check out part one, part two, part three, part four, part five, part six, and part seven.

Restrict

The restrict property defines how a directive can be used. There are four different ways that Angular can find a directive:

  • A: If the restrict attribute contains an A, then the directive can be used as an attribute name. It would be used like this:


    <div dci-testdirective dataprovider="objectArray"></div>

  • E: If the restrict attribute contains an E, then the directive can be used as its own element. This is what we've been doing in this whole article series:


    <dci-testdirective dataprovider="objectArray" ></dci-testdirective>

    This is my preferred method for using directives.

  • C: If the restrict property contains a C, then that directive can be used as part of a CSS class:

    <div class="dci-testdirective" dataprovider="objectArray"></div>
  • M: If the restrict property specifies M that means the directive can be used as an HTML Comment.


    <!-- directive: dci-testdirective expression -->

    When using a directive as an HTML comment, there is no easy way to pass in values. The expression mentioned above will be accessible inside the link function as part of the attrs parameter; but the result must be a string; it is not easy to pass in complicated values such as arrays or other dynamic values. Comment directive are the least common and I believe this is why.

If you want your directive to be available in all methods, you can do this:


restrict : 'AECM',

For most practical purposes, I'll do this:


restrict : 'AE',

This makes the directive available as an attribute and as an element.

Put Directive in its own Module

The next thing I want to cover is how to put the directive into its own module. This, basically, gives the directive its own space in the world of Angular applications. That space can be passed around to other modules that need to use it.

First, let's review how the directive is currently defined:


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

The directive is created using the directive function of an Angular module. The angular module is in this case refers to the main application used throughout this series. We're going to take that directive out of the main application's module and put it in one of its own:


angular.module('dciDirectiveCollection',[]).directive('dciTestdirective',
function(){
});

With the directive in its own module, the original application will have no way to access it by default. We need to tell the original a module to reference the new directive-specific module. This is done by adding the directive-specific module as an argument to the main module's definition:


angular.module('directiveTestApp',['dciDirectiveCollection']);

The directiveTestApp module now has an argument in its options array, referring to the module which contains the directive we created in this whitepaper. The HTML code does not need to change.

Play with the final app.

By implementing directives in their own module, this increases its reusability. With a js include and adding the options argument the directive can be made available to our full application.

Final Thoughts

This series of articles covered everything you need to know, and more, to get started using directives within your Angular applications. Still, I didn't cover everything. Here are a few areas that you can look into for further study:

  • Controllers: Directives can have controllers. These are often used for communication between nested directives, but could also be used similar to the link function.
  • Transclusion: An Angular directive can wrap HTML. This is useful because the wrapped HTML is treated as part of the source controller, not part of the directive. It can access scope variables and methods from the controller even though visually it is displayed as part of the directive.
Such topics will have to wait for another day. Thanks for reading!

Sign up for our 30 page white paper on Angular Directives

Call a Method inside a Directive - Building Angular Directives - Part 7

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

This post will show you how to execute a method inside the directive.

Be sure to check out part one, part two, part three, part four, part five, and part six.

Create a Control Wrapper

This series has shown how to pass data into a directive. It discussed how to get data out of a directive. The directive was used to execute an external method. But, is there a way to execute a function inside a directive from the outside?

Angular does not inherently provide a way to execute a method inside a directive. There are a few different methods to accomplish this. I am going to demonstrate my preferred work-around. It is a useful approach when you need to do it. This section will create a method inside the directive to delete an item from the list.

We previously showed how to use the isolated scope to pass values into a directive. Internal changes to the parameters values will automatically be reflected outside the directive. We'll use this same approach to share internal methods externally. The method we're going to expose to the directive will be one to delete an item from the dataprovider array. Create this method inside the directive's link function:


function deleteItem(object){
scope.onDeleteRequest(object);
}

This function is named deleteItem. It accepts a single argument, representing the item that is going to be deleted, and then calls the onDeleteRequest() method. The onDeleteRequest() method is the listener for the click on the x button inside the directive's view. We're reusing the functionality here.

Now, let's expose this method. First, create a control value in the directive's scope:


scope : {
// other scope variables
control : '='
},

Next go to the directive's onInit() method. Initialize the control parameter:


scope.internalControl = scope.control || {};

If no control is passed in, then the internalControl turns into an empty object. Otherwise, we now have a link to the control object from both inside and outside the directive.

Next add the deleteItem() function into the internalControl:


scope.internalControl.deleteItem = deleteItem;

This completes the changes we need to make to the directive. Let's move onto the main application.

Use the Control Wrapper

Inside the controller for the main app, create our own control object:


$scope.dciTestdirectiveControl = {};

Inside the HTML, you can pass this object into the directive:


<dci-testdirective dataprovider="objectArray"
itemdeleted="onItemDelete(deletedObject)"
control="dciTestdirectiveControl">

</dci-testdirective>

This connects the external control wrapper to the inner control wrapper. The HTML UI will use a button to trigger the method inside the directive.

Add a button under the directive:


<button ng-click="onDeleteFirstItemRequest()">Delete First Item</button>

For the sake of this example, we'll always delete the first item in the list. In the controller's scope, implement the onDeleteFirstItemRequest() method:


$scope.onDeleteFirstItemRequest = function(){
$scope.dciTestdirectiveControl.deleteItem($scope.objectArray[0]);
}

This method references the dciTestdirectiveControl wrapper and executes the deleteItem() method on it, passing in the first item in the dataprovider array.

Run the app, click the button and you'll see the first item was removed:

Play with this sample!

What's Next

This post focused on a work around to what I consider a limitation of Angular directives. Sometimes executing a method inside a directive is an important piece of building the API.

There is one last topic to cover in this series about directives. Next week, I'll show you some tricks you can use to prepare your directive for reuse between different applications.

Sign up for our 30 page white paper on Angular Directives

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.