Jeffrey Roosendaal Jeffrey Roosendaal - 28 days ago 16
Javascript Question

How to properly use the same AngularJS 1.5 component multiple times in a view?

I'm creating a set of widgets with AngularJS 1.5's new components. The problem is, when using the same widget multiple times, they somehow share their controller or scope. I thought one of the things about components was that their scope is completely isolated?




My main html template which hold the widgets:

<widget-list
title="Books"
class="col-xs-12 col-md-4">
</widget-list>

<widget-list
title="Movies"
class="col-xs-12 col-md-4">
</widget-list>

<widget-list
title="Albums"
class="col-xs-12 col-md-4">
</widget-list>


My widget template:

<div class="widget widget-list">
<div class="panel b-a">

<div class="panel-heading b-b b-light">
<h5>{{$widget.title}}</h5>
<div class="pull-right">
<button type="button" class="btn btn-default btn-sm" ng-click="$widget.doSomething()">
Do something
</button>
</div>
</div>

<div class="panel-content">
{{$widget.content || 'No content'}}
</div>

</div>
</div>


My widget component:

app.component('widgetList', {
templateUrl: 'template/widget/widget-list.html',
bindings: {
title : '@',
},
controllerAs: '$widget',
controller: function($timeout) {

$widget = this;

console.log('Title on init: ', $widget.title)

$timeout(function() {
console.log('Title after 3 seconds: ', $widget.title)
}, 3000)

$widget.doSomething = function() {
$widget.content = "Something";
}
}
});





When running my code, this is what my console looks like:

Title on init: Books
Title on init: Movies
Title on init: Albums
(3) Title after 3 seconds: Albums





Also after rendering, all three widgets display
No content
in their template. But, when clicking the
doSomething()
button in either one of the three widgets, only the content of the last widget updates to
Something
.

What is happening here? Why are my components not 'isolated'?

Answer

Looks like you have a global variable called $widget here, try this:

var $widget = this;

instead of

$widget = this;

It creates a mess since the $widget variable holds a reference to the controller that has been recently initialized, in this case to the controller of the third component.

Comments