Using $attrs to evaluate attribute with curly braces in it

假装没事ソ 提交于 2019-12-23 16:00:18

问题


I am creating a file upload directive which uses the following markup.

<file-upload
    name="myUploader"
    upload-url="{{$root.apiSettings.apiUrl}}/files"  
    auto-upload="true"
></file-upload>

I am trying to get the upload-url attribute in the directive controller like this.

$scope.uploadUrl = $attrs.uploadUrl

Obviously this doesn't work as I just get the un-evaluated expression with the curly braces in it. I tried using $scope.$eval to evaluate it but I got a parse error saying { was an invalid character at column 2.

Next i tried using ng-attr-upload-url with and without using $eval on it.

I'm generally trying to avoid using isolate scope bindings which would probably do the trick because most of the attributes in my directives are simple one time, one way bindings and I want to cut down on the number of watches so if this can be achieved using the humble $attrs collection I'd love to know how.


回答1:


In directives scope binding happens at a very later stage in the link and the controller gets executed very early so if you want to get the values provided in attributes of the directive in your directive's controller you need to use $interpolate in your controller , considering you are not using isolated scope.

To get the proper value in the controller you can use either $parse or $interpolate depending upon what you have passed through your directive's attributes. If you passed just the name of the property then you can use $parse otherwise if you have an interpolated string you need to use $interpolate which gets executed in the given context.

In your case you need to use $interpolate like below

In HTML

  <body ng-app='app' ng-controller='mCTRL'>
    <h1>Hello Plunker!</h1>
    <file-upload
    name="myUploader"
    upload-url="{{url}}/files"  
    auto-upload="true"
     ></file-upload>
  </body>

Your Directive should look like below

app.directive('fileUpload',function(){

  return{
    restrict:'EA',
    controller:function($scope,$attrs,$interpolate){
     var myUrl=$interpolate($attrs.uploadUrl)($scope)
    },
    link(scope,elem,attrs,ctrl){

    }

  }

})



回答2:


You can access your directive's attributes through it's link function shown below, you can use this to set the value from the attribute

main.directive('fileUpload', function () {
    return {
    ...
    link: function ($scope, elem, attr) {

        $scope.uploadUrl = attr.upload-url; //note attr.upload-url might cause problems, not sure if you can have dashed attribute names

    }
};

});




回答3:


If you put your logic in a link function instead of a controller, then the attrs.uploadUrl passed to the attrs argument of that link function will already be interpolated for you. That is how I would recommend solving your problem, although the solution proposed by Rishi will work as well.

app.directive('fileUpload', function() {
  return {
    restrict : 'EA',
    link : function(scope, elem, attrs) {
      var myUrl = attrs.uploadUrl;
    }
  };
});

The only reason I have ever found to use a directive controller rather than a link function is when I actually want to inject that controller into another directive via the require property for facilitating inter-directive communication.

Note however that if some parent directive defines scope properties you want interpolated in its own post-link function, they will not be defined yet in a descendant's post-link, as those run in reverse from leaf to root. If you run into that issue you should use the pre-link function to define such properties on the scope so that they are available where you want them.



来源:https://stackoverflow.com/questions/37913102/using-attrs-to-evaluate-attribute-with-curly-braces-in-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!