17

I'd like to write HTML similar to:

<a href="sharedasset: img.png">test</a>
<img src="sharedasset: img.png"/>

And have a directive called "sharedasset" that gets the full path to img.png and sets the value of the attribute without the directive having any knowledge of what the attribute name is ahead of time. Is this possible?

Update

Since I originally posted this there have been some improvements to Angular and I thought I'd share what I do now as a result. In the HTML I use Guido Bouman's answer which is to create a filter and, now with Angular's bind once feature, this makes it the best option in my opinion.

In the JS code though, instead of injecting $filter and my globalVars constant everywhere, now I just prepend the word static to any path of an asset that is hosted on the static content server like {templateUrl: "static/someTemplate.html"} and then use an Angular HTTP Interceptor to look for any path that begins with "static" and replace it with the domain for the static server. Very simple.

adam0101
  • 29,096
  • 21
  • 96
  • 174

3 Answers3

57
<a full-path="img.png">test</a>
<img full-path="img.png">

app.directive('fullPath', function() {
    return {
        link: function(scope, element, attrs) {
            var fullPathUrl = "http://.../";
            if(element[0].tagName === "A") {
                attrs.$set('href',fullPathUrl + attrs.fullPath);
            } else {
                attrs.$set('src',fullPathUrl + attrs.fullPath);
            }
        },
    }
});

I don't know where you are getting fullPathUrl from, so I hardcoded it in the link function.

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • 1
    This is close, but it has 'href' hard-coded in the directive. What if I want to use the directive on an ` – adam0101 Aug 13 '13 at 21:27
  • @adam0101, define another directive, or make the one directive smarter to check the tag type: `if(element[0].tagName === "A") { ... } else { ... }`. – Mark Rajcok Aug 13 '13 at 21:30
9

I didn't want the directive to care what the attribute name was, so this is what I ended up doing:

<a shared-asset="images/img.png" attr="href">test</a>
<img shared-asset="images/img.png" />

app.directive('sharedAsset', function (globalVars) {
    return {
        restrict: "A",
        scope: {
            attr: "@attr"
        },
        link: function (scope, element, attrs) {
            var fullPath = globalVars.staticWebsite + "/app/styles/main/" + attrs.sharedAsset + "?build=" + globalVars.buildNumber;

            attrs.$set(scope.attr || "src", fullPath);
        }
    };
});

Update: I changed it to default to the "src" attribute since images will be the most common scenario.

adam0101
  • 29,096
  • 21
  • 96
  • 174
  • So you do practically the same thing as Mark but mark your own answer as the answer. Very nice. – Blackunknown Sep 30 '14 at 07:59
  • @Blackunknown, because his answer didn't answer my question. I specifically stated that the attribute name couldn't be known ahead of time but he had it hard-coded. I upvoted his answer because it helped, but marked mine as the answer because it answered my question. – adam0101 Sep 30 '14 at 14:15
  • In my opinion he gave you the answer still. All you did was add in a variable instead of it being hard-coded. A lot of the answers people give here are not going to be 100% what you want in the end. Plus the difference is so minimal. – Blackunknown Oct 01 '14 at 15:07
  • 2
    Whatever, it doesn't matter to me. I just figured the next visitor would want to see the answer that best answered the question. – adam0101 Oct 01 '14 at 16:34
8

A custom filter is much more suited for this case than a directive:

<a href="{{'images/img.png' | fullPath}}">test</a>
<img src="{{'images/img.png' | fullPath}}" />

The filter: (Assuming you have a global filters module)

angular.module('filters').filter('fullPath', function(globalVars) {
  return function(url) {
    return globalVars.staticWebsite + "/app/styles/main/" + url + "?build=" + globalVars.buildNumber;
  };
});
adam0101
  • 29,096
  • 21
  • 96
  • 174
Guido Bouman
  • 3,155
  • 4
  • 22
  • 33
  • I really like this approach. I'll probably do it this way on my next project. I'm assuming if you need to do it programmatically you could use `$filter('fullPath')('images/img.png')` then? – adam0101 Mar 13 '15 at 13:31
  • Yes, that's an advantage as well. – Guido Bouman Mar 13 '15 at 15:14