How to set a native attribute from AngularJS directive?

33,104

Solution 1

<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.

Solution 2

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.

Solution 3

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;
  };
});
Share:
33,104

Related videos on Youtube

adam0101
Author by

adam0101

Axiom Horizons Stop working to make others rich Make more by switching to contracting without fear. Keep more by pooling resources with others like you to save on insurance, invoicing, benefits, and more. Visit https://www.axiomhorizons.com to learn more.

Updated on August 21, 2022

Comments

  • adam0101
    adam0101 almost 2 years

    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.

    • Mark Rajcok
      Mark Rajcok almost 11 years
      How about <a ng-href="{{fullPath}}img.png"> and <img ng-src="{{fullPath}}img.png">? This would require fullPath to be defined in a controller.
    • adam0101
      adam0101 almost 11 years
      I want fullPath to be defined in the directive though.
    • Mark Rajcok
      Mark Rajcok almost 11 years
      The directive can't be used inside the value of href or src.
    • adam0101
      adam0101 almost 11 years
      But on docs.angularjs.org/guide/directive at the top they have the example <span class="my-dir: exp;"></span>. How are they doing it?
    • Mark Rajcok
      Mark Rajcok almost 11 years
      It can be used as a class.
  • adam0101
    adam0101 almost 11 years
    This is close, but it has 'href' hard-coded in the directive. What if I want to use the directive on an <img src=""?
  • Mark Rajcok
    Mark Rajcok almost 11 years
    @adam0101, define another directive, or make the one directive smarter to check the tag type: if(element[0].tagName === "A") { ... } else { ... }.
  • Blackunknown
    Blackunknown almost 10 years
    So you do practically the same thing as Mark but mark your own answer as the answer. Very nice.
  • adam0101
    adam0101 almost 10 years
    @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.
  • Blackunknown
    Blackunknown almost 10 years
    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.
  • adam0101
    adam0101 almost 10 years
    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
    adam0101 over 9 years
    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?
  • Guido Bouman
    Guido Bouman over 9 years
    Yes, that's an advantage as well.