Component-based architecture in AngularJS 1.5+

Loading

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

  1. Encapsulation – Components manage their own logic, HTML, and CSS.
  2. Reusability – Components can be used across different parts of an application.
  3. Readability – Code becomes more structured and easier to understand.
  4. One-Way Data Flow – Reduces unexpected side effects in the application.
  5. Easier to Migrate to Angular 2+ – The component-based approach aligns with Angular 2+ and above.

3. Component vs. Directive

FeatureComponent (.component())Directive (.directive())
Simplified APIYesNo
Restricts ScopeIsolated scope by defaultRequires manual isolation
One-Way Data FlowEncouragedTwo-way binding (default)
ReusableYesYes
TemplateUses an inline or external templateRequires template or templateUrl
Controller SyntaxSimple, follows controllerAsNeeds 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 for message (data from parent to child).
  • &: Function binding for onUpdate (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.

HookDescription
$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');
}
});

Leave a Reply

Your email address will not be published. Required fields are marked *