使用可变元素类型创建指令

时间:2014-07-23 20:35:53

标签: angularjs angularjs-directive

我正在尝试使用下拉选择器“Large”,“Medium”,“Small”创建一个更改html元素类型(h1 / h2 / h3)的指令。我希望它也保留元素的属性。我创建了一个这个例子的小提琴:http://jsfiddle.net/H63Z3/1/

角:

angular.module('app', [])
        .controller('example', function ($scope) {
            $scope.type = 'h2';
        })
        .directive('changeType', function ($compile) {
            return {
                restrict: 'A',
                link: function (scope, element, attributes) {
                    scope.$watch('type', function () {
                        var attrs = element[0].attributes;
                        var newElement = $('<' + scope.type + '>').text(element.text());
                        for (var i = 0; i < attrs.length; i++) {
                            newElement.attr(attrs.item(i).name, attrs.item(i).value);
                        }
                        element.replaceWith(newElement);
                        $compile(element.contents())(scope);
                    });
                }
            };
        });
HTM&amp; L:

<div ng-app="app" ng-controller="example">
    <select ng-model="type" ng-options="k as v for (k,v) in { h1: 'Large', h2: 'Medium', h3: 'Small' }"></select>
    <h1 change-type>Text</h1>

    <div>{{ type }}</div>
</div>

我看到的问题是,在下拉列表进行更改后,在Angular中没有正确更新element属性。似乎该指令未重新应用于新元素。我不确定使用编译功能是否正确答案。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:9)

我花了一些时间研究我决定称之为'变形'的指令。实际上非常有趣,我对结果非常满意。请注意,此解决方案是纯Angular。

注意:当我第一次发布此消息时,我没有注意到您需要持久属性。我已经添加了这个功能。我在编译后添加了我的属性,但如果你想将指令作为属性提供,那么你必须反过来这样做。

HTML

<h1>AngularJS 'Morphling' Directive</h1>
<div ng-app="app" ng-controller="morphTest">
  <strong>Morphling directive type:</strong> <select ng-model="type" ng-options="tag as caption for (tag, caption) in { h1: 'Heading 1', h2: 'Heading 2', h3: 'Heading 3', li: 'List Item', quote: 'Quote', attrDemo: 'Attribute Persistence Demo' }"></select><br />
  <morphling type="type" attr="value">Normal <span style="color: red">{{bindingDemo}}</span> Works</morphling>
</div>

LESS

html, body {
  font-family: sans-serif;
  color: #111;
}

quote {
  display: block;
  margin: 20px;
  font-style: italic;
  &:before,
  &:after {
    content: '"';
  }
}

attrDemo[attr="value"] {
  display: inline-block;
  color: blue;
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  -o-transform: rotate(180deg);
  transform: rotate(180deg);
}

的Javascript

angular.module('app', [])
  .controller('morphTest', function ($scope) {
    $scope.type = 'h2';
    $scope.bindingDemo = 'Binding';
  })
  .directive('morphling', function ($compile) {
    return {
      restrict: 'E',
      replace: true,
      link: function(scope, element, attributes) {
        var e = element;
        scope.$watch(attributes.type, function(type){
          type = !!type ? type : 'span';
          var e2 = $compile('<' + type + '>' + e.html() + '</' + type + '>')(scope);
          for(var a in attributes.$attr) {
            if(a.toLowerCase() != 'type')
              e2.attr(a, attributes[a]);
          }
          e.replaceWith(e2);
          e = e2;
        });
      }
    };
  });

演示

CodePen Demo

答案 1 :(得分:0)

@Michael Mroz

我想指出您提出的解决方案会破坏绑定: http://codepen.io/anon/pen/PwLzQX

angular.module('app', [])
  .controller('morphTest', function ($scope, $interval) {
    $scope.type = 'h2';
    $scope.bindingDemo = 'Binding';

    var i = 0;
    $interval(function() {
      $scope.bindingDemo = 'Binding ' + ++i;
    }, 1000);
  })
  .directive('morphling', function ($compile) {
    return {
      restrict: 'E',
      replace: true,
      link: function(scope, element, attributes) {
        // return; // uncomment here

        var e = element;
        scope.$watch(attributes.type, function(type){
          type = !!type ? type : 'span';
          var e2 = $compile('<' + type + '>' + e.html() + '</' + type + '>')(scope);
          for(var a in attributes.$attr) {
            if(a.toLowerCase() != 'type')
              e2.attr(a, attributes[a]);
          }
          e.replaceWith(e2);
          e = e2;
        });
      }
    };
  });

您应该看到&#34;正常绑定[数字]工作&#34;随着[数字]递增,但它没有显示。

取消回报;在链接功能中,您将看到绑定工作。