3

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

scheffield
  • 6,618
  • 2
  • 30
  • 31

2 Answers2

2

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.

Community
  • 1
  • 1
michael
  • 16,221
  • 7
  • 55
  • 60
  • Mh, maybe I'm on the wrong track, but is a filter semantically correct? At least, it should filter something... – scheffield Jan 09 '14 at 20:15
  • 1
    i think not. the documentation stated: "A filter formats the value of an expression for display to the user. They can be used in view templates, controllers or services and it is easy to define your own filter." http://docs.angularjs.org/guide/filter There are a lot of filters that do exactly this (date, currency, json, lowercase,...) your problem can be described in this way: "format my object as a link that is displayed to the user" the filter creates a string nothing less nothing more. IMHO that we use this string as a link to an image is covered by the law :) – michael Jan 09 '14 at 20:23
  • to be closer to the filter definition I wrote a filter like this: `{{4711|userImage:'small'}}` – scheffield Jan 10 '14 at 12:45
  • yepp! looks angularish – michael Jan 10 '14 at 13:25
0

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.

Hylianpuffball
  • 1,553
  • 10
  • 13