Check out our new training course on AngularJS for Flex Developers

Setting a Default State - AngularJS UI Router - Part 2

This is part of a series of posts about the AngularJS UI Router. Check out article 1.

The biggest problem with part 1 of this series was that no default state was set, so the app would load a blank screen. That is something that needs to be addressed. I could use two different ways to set up a default state, and I'm going to explain both of them here.

Create a state with no URL

The first approach to creating a default state is to create a state with an empty URL attribute. Do this in the config that defines the states with the $stateProvider:


angular.module('routerTestApp').config(['$stateProvider',
function($stateProvider){
$stateProvider
.state('state1', {
url: '/state1',
templateUrl : 'states/state1.html'
})
.state('state2', {
url: '/state2',
templateUrl : 'states/state2.html'
})
.state('default', {
url: '',
templateUrl : 'states/state1.html'
})
}
]);

The new state is added at the end. The name of the state is default, and the url parameter is an empty string. This will make it so that upon initial load the application--with no URL variables--the state1.hml template will load. Now upon initial load the app, you'll see the correct state loaded even if you don't specify it in the URL:

Play with the app here.

As I congratulated myself on the creativity of this approach, I realized a limitation of this very quickly. If I want state1 to equal the default state, then every property of the state1 object will need to be defined as part of the state2 object, so it feels like some duplication of code.

Set a default state with the $urlRouteProvider

The uiRouter provides a standard way to set the default state. Into the config you can pass a uiRouter service named $urlRouteProvider. This service can be used to specify the default state:


angular.module('routerTestApp')
.config(['$stateProvider','$urlRouterProvider',
function($stateProvider,$urlRouterProvider){
$urlRouterProvider.otherwise("/state1");
// other state setup code here
}
]);

The otherwise() function is called on the urlRouteProvider and it accepts a single string. If no state is loaded, then the otherwise state will be specified.

Load the new app to see the initial state load:

Play with the code here.

I prefer using the $urlRouteProvider to set a default state on the application.

Final Thoughts

The next article in this series will show you how to associate a controller with the state. Controller's are the part of AngularJS that include business logic.

We wrote 20 pages on the Angular uiRouter, sign up to get it!

Switching Between Two States - AngularJS UI Router - Part 1

This is the first in a series of blog posts about the AngularJS UI Router.

Part of the AngularJS library is a router, named ngRoute. The ngRoute library allowed you to show different views of your Angular application based on the URL in the browser. This works great for simple applications; however it has some distinct limitations. Only a single view can be displayed per URL and nested views are not supported. Applications often have multiple views, such as a header, footer, and some main content. Main content is often split up into multiple sections. The ngRoute directive can only bring us so far.

The AngularUI team has created an alternate router, uiRouter, to addresses some of the limitations of the ngRoute. The ngRoute directive approaches an application as a collection of URLs, each one displaying a different view. The uiRouter looks at an application as a collection of states, and it allows multiple, nested states. This is a series of blog posts about using the uiRouter within an AngularJS application.

Switching Between Two States

The first sample will show you how to switch between two separate states.

Create the Application Skeleton

First, import the Angular library and the ui-router library:


<script src="//code.angularjs.org/1.5.8/angular.min.js"></script>
<script
src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.1/angular-ui-router.min.js">

</script>

I reference both libraries from hosted CDN instead of copying them locally as part of my application. Next, create an Angular app in a script block:


<script>
angular.module('routerTestApp', ['ui.router']);
</script>

Configure the UI Router

A single configuration argument is passed into the Angular module, ui.router. This tells the Angular Module--routerTestApp--to load the uiRouter code and make it available to the application. This sample will create two UI States, state1 and state2. The router configuration is done in an Angular config block.


angular.module('routerTestApp').config(['$stateProvider',
function($stateProvider){
$stateProvider
.state('state1', {
url: '/state1',
templateUrl : 'states/state1.html'
})
.state('state2', {
url: '/state2',
templateUrl : 'states/state2.html'
})
}
]);

A service named $stateProvider is passed into the config block using the Angular dependency injection syntax. The $stateProvider service is part of the UI-router and is analogous to the $routeProvider used as part of ngRoute. The $stateProvider is used to define the two states of the application. In this case, a URL is defined. This is the value that will display in the URL when the state is displayed. A templateURL is used to refer to an HTML page that contains the view code that will be displayed when the state is active.

Create the HTML

First, we'll create the two HTML templates. The first is state1.html:


<h1>State 1</h1>
<a ui-sref="state2">Go to State 2</a>

This template is very simple. It includes a header with simple text stating 'State 1'. The anchor link is a bit more interesting. It includes an Angular directive named uiSref. This directive tells the uiRouter library to load a new state and change the URL whenever that link is clicked. The value of the uiSref directive is the name of the state that should be loaded. If the state doesn't exist, the anchor is immediately disabled and does not present the user with a link.

The state2.html template is almost identical to state1.html:


<h1>State 2</h1>
<a ui-sref="state1">Go to State 1</a>

The header says 'State 2' instead of 'State 1'. The link goes back to state1 instead of state2. The main index needs some HTML to make this work too. First, add the ngApp directive to the body tag:


<body ng-app="routerTestApp">

Then, add the ui-view:


<div ui-view></div>

The uiView directive tells the uiRouter directive to put the view here.

Test the App

Load the app in a browser, be sure to specify the current state with a URL like '/Index.html#/state1'. You should see the first state:

Click the link to open state 2. State2 should open:

The URL should change and state2 is displayed on the screen.

Play with the code here.

Final Thoughts

The Plunker is a bit tricky to work with given the current codebase, because no default state is specified for the initial load of the application. Without a default state, neither state1 or state2 will be displayed unless you specify the state in the URL when you load the application.

The next article in this series will address that.

We wrote 20 pages on the Angular uiRouter, sign up to get it!

Why use Angular's $log instead of JavaScript's console.log()?

console.log() is a great debugging technique when writing JavaScript code. It immediately prints a variable or text to the browser's console and you can use that to keep track of code that has run flawlessly. AngularJS provides a $log service that provides the same functionality. Why would we want to use one over the other?

Using console.log()

I use console.log() a lot, and it is probably sprinkled all over the samples I've written about in this blog. It is easy to use.

In any part of JavaScript, just add a line like this to output a constant:


console.log('some constant');

Use a line like this to output a variable:


var myVar = 'Some Variable';
console.log(myVar);

You can play with this code here.

It is a really simple sample, but can be valuable when you want to drill down into an object being returned from a service or something similar.

Using AngularJS's $log service

Angular requires more setup. First, import the Angular library:


<script data-require="angular.js@1.5.7" data-semver="1.5.7" src="https://code.angularjs.org/1.5.7/angular.js"></script>

Then in a Script block, create an Angular module:


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

Create an Angular controller, injecting the $log service into the controller function:


angular.module('mySimpleApp').controller('myController', ['$log',function($log){
}]);

Finally, perform the outputs similar to how we did in our console.log() example:


$log.debug('some constant')

var myVar = 'Some Variable';
$log.debug(myVar);

You can play with this code here.

You'll see the two samples operate very similarly.

Why use $log?

The main reason for using $log is for encapsulation purposes. When writing tests for your Angular controllers or services, it is better to have an object which you can easily mock. The Angular log service can be replaced during the Angular injection process. console.log() cannot be. I still use console.log() for quick and dirty debugging, primarily because that is what I learned first. For a more testable, encapsulated approach, go with the $log service.

How do I Disable an HTML Element with AngularJS?

I was working on a client application which was creating a lot of duplicate entries in a database. After some research, we learned that our users were clicking the submit button multiple times, causing multiple service calls, which was causing multiple database entries to be created.

We decided the solution was to disable the submit button. AngularJS makes it easy by using the ngDisabled directive.

Set up the App

First, import the Angular library:


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

Then, create a sample Angular Module and controller:


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

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

I'm going to add two $scope variables to the controller for this sample:


$scope.buttonDisabled = false;
$scope.buttonDisabledButtonLabel = "Disable";

The buttonDisabled is a boolean value that will be used to toggle the ngDisabled property on the button in question. The buttonDisabledButtonLabel will be used as part of the label of the button which will trigger the disabled event.

Create the View

Let's create the HTML view.


<body ng-app="sampleApp">
<div ng-controller="disableSampleCtrl">
</div>

The Angular Module is attached the body tag with the ngApp directive. The controller is added to a div.

Inside the controller's view I'm going to be put two buttons:


<button ng-disabled="buttonDisabled" ng-click="onSubmitClick()">Submit</button>
<button ng-click="toggleDisableButton()">{{textDisabledButtonLabel}} Submit Button</button>

The first button is the button that gets disabled. In addition to the ngDisabled tag, whose value relates to the buttonDisabled property in the controller; there is also an ngClick attribute, so that the button can execute a controller function when it is clicked.

The second button is used to toggle the disabled property of the first.

Implement the Button Functions

Let's implement the controller functions for the buttons. First, implement the toggleDisableButton property:


$scope.toggleDisableButton = function(){
$scope.buttonDisabled = !$scope.buttonDisabled
if($scope.textDisabled){
$scope.buttonDisabledButtonLabel = "Enable";
} else {
$scope.buttonDisabledButtonLabel = "Disable";
}
}

This button swaps the value of the buttonDisabled property. It also changes the value of the buttonDisabledButtonLabel. This refers back to the label of the button that causes the disable / enablement.

The submit button also triggered a method when clicked:


$scope.onSubmitClick = function(){
console.log('something happened');
}

This function simple logs value out to the console; so you can tell whether or not the button is clickable.

Final Thoughts

Play with this App!

For the sake of completeness, in the plunker code I also demonstrated how to enable / disabled a text input.

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

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.