AngularJS 1.5 introduced the component-based architecture to make applications more modular, reusable, and maintainable. The component()
method simplifies directive creation and encourages breaking down the application into self-contained, reusable components.
1. What is Component-Based Architecture?
Component-based architecture is a design pattern where applications are built using small, independent, and reusable components. In AngularJS 1.5+, components replace traditional directives and follow the one-way data flow and component hierarchy approach.
2. Benefits of Using Components
- Encapsulation – Components manage their own logic, HTML, and CSS.
- Reusability – Components can be used across different parts of an application.
- Readability – Code becomes more structured and easier to understand.
- One-Way Data Flow – Reduces unexpected side effects in the application.
- Easier to Migrate to Angular 2+ – The component-based approach aligns with Angular 2+ and above.
3. Component vs. Directive
Feature | Component (.component() ) | Directive (.directive() ) |
---|---|---|
Simplified API | Yes | No |
Restricts Scope | Isolated scope by default | Requires manual isolation |
One-Way Data Flow | Encouraged | Two-way binding (default) |
Reusable | Yes | Yes |
Template | Uses an inline or external template | Requires template or templateUrl |
Controller Syntax | Simple, follows controllerAs | Needs explicit controller definition |
4. Creating a Simple Component
Step 1: Setting Up an AngularJS App
Ensure you include AngularJS 1.5+ in your project:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
Step 2: Defining a Component
Create a simple helloWorld
component:
var app = angular.module('myApp', []);
app.component('helloWorld', {
template: '<h1>Hello, {{$ctrl.name}}!</h1>',
controller: function() {
this.name = 'AngularJS 1.5';
}
});
Step 3: Using the Component
Modify index.html
:
<div ng-app="myApp">
<hello-world></hello-world>
</div>
Explanation:
template
: Defines the HTML structure.controller
: Defines the component’s logic.$ctrl
: Default alias for the controller (instead of$scope
).- Usage:
<hello-world></hello-world>
5. Passing Data Using Bindings
Components allow input properties (@
, <
, &
) for passing data.
Component with Input Binding (<
)
Modify app.js
:
app.component('greetUser', {
bindings: {
username: '<'
},
template: '<p>Welcome, {{$ctrl.username}}!</p>',
controller: function() {
console.log('User:', this.username);
}
});
Modify index.html
:
<div ng-app="myApp">
<greet-user username="'John Doe'"></greet-user>
</div>
Explanation:
<
: One-way data binding.- Usage:
<greet-user username="'John Doe'"></greet-user>
6. Communication Between Components
Components communicate via bindings and events.
Parent Component
Modify app.js
:
app.component('parentComponent', {
template: `
<h2>Parent Component</h2>
<child-component message="parent.message" on-update="parent.updateMessage(msg)"></child-component>
<p>Updated Message: {{parent.message}}</p>
`,
controller: function() {
this.message = "Hello from Parent!";
this.updateMessage = function(msg) {
this.message = msg;
};
},
controllerAs: 'parent'
});
Child Component
Modify app.js
:
app.component('childComponent', {
bindings: {
message: '<',
onUpdate: '&'
},
template: `
<h3>Child Component</h3>
<p>Message from Parent: {{ $ctrl.message }}</p>
<input type="text" ng-model="newMessage">
<button ng-click="$ctrl.onUpdate({ msg: newMessage })">Update Parent</button>
`,
controller: function() {}
});
Usage in index.html
<div ng-app="myApp">
<parent-component></parent-component>
</div>
Explanation:
<
: One-way binding formessage
(data from parent to child).&
: Function binding foronUpdate
(child updates parent’s data).- Clicking Update Parent sends new data to the parent component.
7. Lifecycle Hooks in Components
AngularJS 1.5 components introduce lifecycle hooks similar to Angular.
Hook | Description |
---|---|
$onInit() | Runs after component initialization. |
$onChanges(changes) | Called when a binding value changes. |
$onDestroy() | Executes before component is destroyed. |
Example Using Lifecycle Hooks
app.component('lifecycleComponent', {
bindings: { data: '<' },
template: '<p>Data: {{$ctrl.data}}</p>',
controller: function() {
this.$onInit = function() {
console.log('Component Initialized!');
};
this.$onChanges = function(changes) {
console.log('Data Changed:', changes.data.currentValue);
};
this.$onDestroy = function() {
console.log('Component Destroyed!');
};
}
});
8. Nested Components Example
A dashboard with multiple widgets.
Dashboard Component
app.component('dashboard', {
template: `
<h2>Dashboard</h2>
<widget title="'Users'" content="'50 Active Users'"></widget>
<widget title="'Sales'" content="'$5000 Revenue'"></widget>
`
});
Widget Component
app.component('widget', {
bindings: {
title: '<',
content: '<'
},
template: `
<div class="widget">
<h3>{{ $ctrl.title }}</h3>
<p>{{ $ctrl.content }}</p>
</div>
`
});
Usage in index.html
<div ng-app="myApp">
<dashboard></dashboard>
</div>
9. Migrating from Directives to Components
If you have an existing directive like:
app.directive('myDirective', function() {
return {
restrict: 'E',
scope: { name: '@' },
template: '<p>Hello, {{name}}</p>',
controller: function($scope) {
console.log('Directive Loaded');
}
};
});
Convert it to a component:
app.component('myComponent', {
bindings: { name: '@' },
template: '<p>Hello, {{$ctrl.name}}</p>',
controller: function() {
console.log('Component Loaded');
}
});