scheffield
scheffield

Reputation: 6787

global utility function vs. directive

Task:

Build a utility function to build a configurable URL. The URL pattern looks like that

/images/<size>/users/<user_id>

Possible Solutions

1. Build a directive. It could look like follows:

<img my-user-img my-size="small" my-user="4711" />

This is a little bit ugly since I have to add all the boilerplate to support multiple arguments.

2. Build a util/helper function. It could look like follows:

<img ng-src="{{userImg('small', '4711')}}" />

This is ugly since I have to bind the function to $rootScope in order to use it everywhere .

The Question

Which solution is the closest to Best Practice and why? :D

Upvotes: 3

Views: 591

Answers (2)

Hylianpuffball
Hylianpuffball

Reputation: 1561

Angular services (also factories) work great for utility stuff. Put your function into a service, and it becomes injectable into any controller anywhere.

myModule.service("CoolThingDoer", function(){
  this.niftyMethod = function(param){ /* ... blah blah ... */}
});

and later

myModule.controller("DisplayController", ['$scope','CoolThingDoer', function($scope,CoolThingDoer){
  //...
  $scope.nifty = CoolThingDoer.niftyMethod("Cool");
  //...
}]);

Now, I agree with Michael that what you're looking for is more along the lines of a filter, but other visitors coming to this question may want to check our services instead, and they're usually more resuable and robust.

Upvotes: 0

michael
michael

Reputation: 16341

neither 1 or 2. you have the answers provided! i would suggest use a filter with multiple parameter: see: How do I call an Angular.js filter with multiple arguments?

first possible solution with parameter:

filter('userImage', function(){
  return function(val, size, user){
     return '/images/'+size+'/users/'+user;
  };
});

usage:

{{''|userImage:'small':'4711'}}

Instead of '' one could use angular.noop.

if you dont like the '' as noop expression, there is another possibility:

filter('createLink', function(){
  return function(params){
     return '/images/'+params.size+'/users/'+params.user;
  };
});

usage:

{{{size:'small', user:'4711'}|createLink}}

Especially the last solution gives you the possibility use a domain object directly without any mapping.

Upvotes: 2

Related Questions