Components and Multiple Transclusion in Angular 1.5

According to the Angular’s site, a component is a special kind of directive that uses a simpler configuration which is suitable for a component-based application structure.

angular. 
.module('myApp')
.component('testComponent', {
template: "<div>Hi there, i am a component</div>",
controllerAs: "vm", //if not angular will set it as $ctrl
controller: function() {
var vm = this; vm.foo = bar;
}
});

What are the differences?

New lifecycle hooks

<div ng-controller="TestController">
<testDirective></testDirective>
</div>
<testComponent></testComponent>

Components vs Directives

angular. 
.module('myApp')
.component('testComponent', {
// the rest of the information is omitted for
//convenience
bindings : {
foo : "<", // objects
bar : "@", //strings
baz : "&" //events
}
});
};
<li ng-repeat="bar in bars"> 
<testComponent foo="myObj.name"bar="myObj"></testComponent>
</li>
angular. 
.module('myApp')
.component('testComponent', {
// the rest of the information is omitted for
//convenience
transclude : true
});
};

Advantages of Components:

* simpler configuration than plain directives * promote sane
defaults and best practices
* optimised for component-based
architecture
* writing component directives will make it easier to
upgrade to Angular 2

When not to use Components:

* for directives that rely on DOM manipulation, adding event
listeners etc, because the compile and link functions are
unavailable
* when you need advanced directive definition options like priority, terminal,
multi-element
* when you want a directive that is triggered by an attribute or CSS class,
rather than an element

Unit Testing

describe("Testing my TestComponent", function() {
beforeEach(module("myApp"));
var testComponentController;
beforeEach(inject(function($componentController){
testComponentController =
$componentController("testComponent", {
// all the dependencies we want to mock
$scope : {}
});
}));
it("can be tested", function() {
expect(testComponentController).toBeDefined();
expect(testComponentController.$onInit).toBeDefined();
expect(testComponentController.$onChanges).toBeDefined();
expect(testComponentController.$onDestroy).toBeDefined();
});
});

Multiple Transclusion… wait… what?

In computer science, transclusion is the inclusion of part or all of an electronic document into one or more other documents by reference.

Single Transclution

<task-item task="{ name: 'this is a task obj'}"> 
No selective transclusion, this will be transclude with options and placed
after the text
<hr />
<div class="options">
<span ng-click="save()">Save</span> -
<span ng-click="delete()">Delete</span>
</div>
</task-item>
angular 
.module("myApp")
.directive('taskItem', function () {
return {
restrict: 'E',
transclude: true,
scope : {
task : "="
},
template: "<div class='task'>{{ task.name }} <hr />" +
"<ng-transclude></ng-transclude></div>"
}
});
<task-item task="{ name: 'this is a task obj'}" class="ng-isolate-scope"> 
<div class="task ng-binding">
this is a task obj
<hr> <span> No selective transclusion,
this will be transclude with options and placed after the text </span>
<hr>
<div class="options">
<span ng-click="save()">Save</span> -
<span ng-click="delete()">Delete</span>
</div>
</div>
</task-item>

Messing around multiple transclusion

<task-item-multiple task="{ name: 'this is a task obj for sample2'}"> 
<span>
1. Using selective transclusion, this will be transcluded and magically
placed below the options
</span>
<div class="options">
2. <span ng-click="save()">Save</span> -
<span ng-click="delete()">Delete</span>
</div>
<hr />
</task-item-multiple>
angular 
.module("myApp")
.directive('taskItemMultiple', function() {
return {
restrict: 'E',
transclude: {
//we can set a new identifier
'new': 'span' //could be a div, why not?
},
scope: {
task: "="
},
//Let's change the order of elements
template: "<div ng-transclude></div>" +
"<div>{{task.name}}</div><hr>" +
"<div ng-transclude='new'></div>"
}
});
<task-item-multiple task="{ name: 'this is a task obj for sample 2'}" 
class="ng-isolate-scope">
<div ng-transclude="">
<div class="options ng-scope">
2. <span ng-click="save()">Save</span> -
<span ng-click="delete()">Delete</span>
</div>
<hr class="ng-scope">
</div>
<div class="ng-binding">
this is a task obj for sample 2
</div>
<hr>
<div ng-transclude="new">
<span class="ng-scope">
1. Using selective transclusion, this will be transclude and
magically placed below the options
</span>
</div>
</task-item-multiple>
transclude: { 'new' : '?span' }

--

--

yep.. i’m an asshole🤷🏻‍♂️

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store