3
\$\begingroup\$

I have a very simple directive <my-card> that lists out some data.

Example Usage

my-card(ng-repeat="item in parentCtrl.items" item='item')

The only main functionality I have is a button that toggles some additional data.

Here is my directive/controller definition. Should I use the link function instead of creating a controller? The reason I moved the logic into the MyCardCtrl was so that I can easily unit test it.

MyCardCtrl

 function MyCardCtrl() {
 var vm = this;
 this.cardClass = 'my-card-' + vm.item.type;
 this.toggle = function() {
 vm.item.showMore = !vm.item.showMore;
 };
 this.init = function(element) {
 var img = angular.element(element[0].querySelector('.card-bg'));
 img.css('background-image', 'url(' + vm.item.image_url + ')');
 };
 }

myCard Directive

 function myCard() {
 return {
 restrict: 'E',
 replace: true,
 templateUrl: 'my-card.html'
 scope: {
 item: '='
 },
 link: function(scope, element, attrs, myCardCtrl) {
 myCardCtrl.init(element);
 },
 controller: 'MyCardCtrl',
 controllerAs: 'card',
 bindToController: true
 };
 }
 angular
 .module('components')
 .directive('myCard', [myCard])
 .controller('MyCardCtrl', [MyCardCtrl]);

myCard template (written in Jade)

 .my-card(ng-class='class.cardClass')
 button(ng-click='card.toggleMeta()')
 .my-card-content(ng-show='card.item.showMore')
 // expose item object
 h1 {{::item.name}}
 .my-card-more(ng-show='!card.item.showMore')
 .my-card-bg
asked Aug 30, 2016 at 17:46
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Just get rid of the link function entirely. You can set the background-image in the template with ng-style, and then you have one less function to worry about:

.my-card(ng-style='{"background-image": "url(" + card.item.image_url + ")"}', ng-class='card.cardClass')
 button(ng-click='card.toggle()')
 .my-card-content(ng-show='card.item.showMore')
 h1 {{::card.item.name}}
 .my-card-more(ng-show='!card.item.showMore')
 .my-card-bg

If you want to build up the url(card.item.image_url) string in the controller for easier testing, you can still use ng-style to apply the resulting variable. For example:

function MyCardCtrl() {
 var vm = this;
 vm.backgroundUrl = 'url("' + vm.item.image_url + '")';
 vm.cardClass = 'my-card-' + vm.item.type;
 vm.toggle = function() {
 vm.item.showMore = !vm.item.showMore;
 };
}

Also, if you're on Angular 1.5+, this directive can be written even more simply as a component:

angular
 .module('components')
 .component('myCard', {
 bindings: {
 item: '<'
 },
 templateUrl: 'my-card.html',
 controller: 'MyCardCtrl',
 controllerAs: 'card'
 })
 .controller('MyCardCtrl', [MyCardCtrl]);
answered Aug 31, 2016 at 7:56
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.