Использование $attrs для оценки атрибута с фигурными скобками в нем

Я создаю директиву загрузки файлов, которая использует следующую разметку.

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

Я пытаюсь получить атрибут upload-url в контроллере директив, как это.

$scope.uploadUrl = $attrs.uploadUrl

Очевидно, это не сработает, так как я просто получаю необработанное выражение с фигурными скобками. Я попытался использовать $scope.$ Eval для его оценки, но я получил ошибку синтаксического анализа, говорящую, что {был недопустимый символ в столбце 2.

Затем я попытался использовать ng-attr-upload-url с и без использования $eval.

Как правило, я стараюсь избегать использования изолированных привязок области видимости, которые, вероятно, сработают, потому что большинство атрибутов в моих директивах являются простыми однократными, односторонними привязками, и я хочу сократить количество наблюдений, поэтому, если это может быть достигнуто используя скромную коллекцию $attrs, я бы хотел узнать как.

2 ответа

Решение

В директивах привязка области видимости происходит на очень поздней стадии в ссылке, и контроллер выполняется очень рано, поэтому, если вы хотите получить значения, предоставленные в атрибутах директивы в контроллере вашей директивы, вам нужно использовать $interpolate в вашем контроллере, учитывая, что вы не используете изолированную область.

Чтобы получить правильное значение в контроллере, вы можете использовать либо $parse или же $interpolate в зависимости от того, что вы прошли через атрибуты вашей директивы. Если вы передали только имя свойства, то вы можете использовать $parse, иначе, если у вас есть интерполированная строка, вам нужно использовать $interpolate, который выполняется в данном контексте.

В вашем случае вам нужно использовать $interpolate, как показано ниже

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

Ваша директива должна выглядеть ниже

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

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

    }

  }

})

Если вы поместите свою логику в функцию ссылки вместо контроллера, тогда attrs.uploadUrl, переданный в аргумент attrs этой функции ссылки, уже будет интерполирован для вас. Вот как я бы порекомендовал решить вашу проблему, хотя решение, предложенное Риши, также подойдет.

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

Единственная причина, по которой я когда-либо использовал контроллер директив, а не функцию ссылки, - это когда я действительно хочу внедрить этот контроллер в другую директиву через свойство require для облегчения междирективного взаимодействия.

Однако обратите внимание, что если какая-либо родительская директива определяет свойства области, которые вы хотите интерполировать в ее собственной функции пост-ссылки, они еще не будут определены в пост-ссылке потомка, поскольку они выполняются в обратном порядке от листа к корню. Если вы столкнетесь с этой проблемой, вам следует использовать функцию предварительной ссылки, чтобы определить такие свойства в области, чтобы они были доступны там, где вы хотите.

Вы можете получить доступ к атрибутам вашей директивы через функцию ссылки, показанную ниже, вы можете использовать ее для установки значения из атрибута

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

    }
};

});

Другие вопросы по тегам