How to prevent duplicated attributes in angular directive when replace=true

前端 未结 2 1932
半阙折子戏
半阙折子戏 2021-01-02 10:59

I\'ve found that angular directives that specify replace: true will copy attributes from the directive usage into the output rendered by the template. If the te

相关标签:
2条回答
  • 2021-01-02 11:13

    It would be helpful to know how you expect the values to be merged. Does the template take priority, the element, or is some kind of merge needed?

    Lacking that I can only make an assumption, the below code assumes you want to remove attributes from the template that exist on the element.

    .directive('foo', function() {
        return {
            restrict: 'E',
            replace: true,
            template: function(element, attrs) {
                var template = '<div bar="{{bar}}" baz="baz"></div>';
                template = angular.element(template);
                Object.keys(attrs.$attr).forEach(function(attr) {\
                    // Remove all attributes on the element from the template before returning it.
                    template.removeAttr(attrs.$attr[attr]);
                });
                return template;
            },
            scope: {
              bar: '@'
            }
        };
    })
    
    0 讨论(0)
  • 2021-01-02 11:17

    No, there isn't some nice declarative way to tell Angular how x attribute should be merged or manipulated when transplanted into templates.

    Angular actually does a straight copy of attributes from the source to the destination element (with a few exceptions) and merges attribute values. You can see this behaviour in the mergeTemplateAttributes function of the Angular compiler.

    Since you can't change that behaviour, you can get some control over attributes and their values with the compile or link properties of the directive definition. It most likely makes more sense for you to do attribute manipulation in the compile phase rather than the link phase, since you want these attributes to be "ready" by the time any link functions run.

    You can do something like this:

    .directive('foo', function() {
      return {
        // ..
        compile: compile
        // ..
      };
    
      function compile(tElement, tAttrs) {
        // destination element you want to manipulate attrs on
        var destEl = tElement.find(...);
    
        angular.forEach(tAttrs, function (value, key) {
          manipulateAttr(tElement, destEl, key);
        })
    
        var postLinkFn = function(scope, element, attrs) {
          // your link function
          // ...
        }
    
        return postLinkFn;
      }
    
      function manipulateAttr(src, dest, attrName) {
        // do your manipulation
        // ...
      }
    })
    
    0 讨论(0)
提交回复
热议问题