Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angularjs 创建具有可变元素类型的指令_Angularjs_Angularjs Directive - Fatal编程技术网

Angularjs 创建具有可变元素类型的指令

Angularjs 创建具有可变元素类型的指令,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我试图创建一个指令,通过使用“大”、“中”、“小”下拉选择器来更改html元素类型(h1/h2/h3)。我希望它还保留元素上的属性。我创建了一个小提琴的例子: 角度: angular.module('app', []) .controller('example', function ($scope) { $scope.type = 'h2'; }) .directive('changeType', function ($co

我试图创建一个指令,通过使用“大”、“中”、“小”下拉选择器来更改html元素类型(h1/h2/h3)。我希望它还保留元素上的属性。我创建了一个小提琴的例子:

角度:

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);
                    });
                }
            };
        });
angular.module('app',[])
.controller('示例',函数($scope){
$scope.type='h2';
})
.directive('changeType',函数($compile){
返回{
限制:“A”,
链接:功能(范围、元素、属性){
范围:$watch('类型',函数(){
var attrs=元素[0]。属性;
var newElement=$('').text(element.text());
对于(变量i=0;i
HTM&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>

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


任何帮助都将不胜感激。

我只是花了一点时间研究我决定称之为“变形”指令的东西。实际上这很有趣,我对结果很满意。请注意,此解是纯角度解

注意:我第一次发布这篇文章时没有注意到您需要持久属性。此后,我添加了该功能。我在编译之后添加属性,但是如果您想提供作为属性的指令,则必须以另一种方式进行

HTML Javascript
angular.module('app',[])
.controller('morphTest',函数($scope){
$scope.type='h2';
$scope.bindingDemo='Binding';
})
.directive('morphing',函数($compile){
返回{
限制:'E',
替换:正确,
链接:功能(范围、元素、属性){
var e=元素;
范围.$watch(attributes.type,function(type){
类型=!!类型?类型:'span';
var e2=$compile(“”+e.html()+“”)(范围);
for(属性中的变量a.$attr){
if(a.toLowerCase()!='type')
e2.属性(a,属性[a]);
}
e、 替换为(e2);
e=e2;
});
}
};
});
演示 @Michael Mroz

我想指出,你提出的解决方案打破了约束:

angular.module('app',[])
.controller('morphTest',函数($scope,$interval){
$scope.type='h2';
$scope.bindingDemo='Binding';
var i=0;
$interval(函数(){
$scope.bindingDemo='Binding'++i;
}, 1000);
})
.directive('morphing',函数($compile){
返回{
限制:'E',
替换:正确,
链接:功能(范围、元素、属性){
//return;//在此处取消注释
var e=元素;
范围.$watch(attributes.type,function(type){
类型=!!类型?类型:'span';
var e2=$compile(“”+e.html()+“”)(范围);
for(属性中的变量a.$attr){
if(a.toLowerCase()!='type')
e2.属性(a,属性[a]);
}
e、 替换为(e2);
e=e2;
});
}
};
});
您应该看到,[number]递增时“正常绑定[number]工作”,但它没有显示


取消对报税表的注释;在link函数中,您将看到绑定工作。

这与您要查找的内容接近吗?[AngularJS-如何更改包含数据绑定的模板中的元素?][1][1]:为什么不创建一个元素指令,根据输入属性更改模板?i、 e.@EdMeacham链接中的解决方案有效,但它将更改的元素嵌套在原始元素中,看起来像:“Text”。我希望页面上只有一个header元素可以更改,以便提取干净的输出标记。这样做的复杂之处在于,必须销毁并重新创建元素,而指令仍然应用于单个标头元素。这是我不确定是否可能的部分,但使用element.replaceWith()似乎应该考虑到这一点。我不确定我的示例中有什么错误。关于@FLoG的“答案”指出了此解决方案中的缺陷:如果在指令中放入一个范围变量并设置一个向上爬行的间隔,它将向上爬行,直到第一次更改为
类型
。是的,这是个问题。如果您需要考虑这种行为,则必须对
$compile
行进行大量修改。此解决方案非常适合我,但当其他属性是对象文本时,我很难让它们正常工作。我对angular在作为属性传递时如何处理对象有点困惑。知道为什么会发生这种情况吗?正如弗洛格指出的,绑定并不完全有效。请注意,我在编译后重新添加了属性。。。这需要在之前完成,但我不知道Angular是否支持使其正常工作所需的反射。每次调用指令都需要访问整个字符串。如果你能从指令中得到,这个解决方案可以改进。事实上,这是绝对可能的,因为否则ngRepeat就不是一件事了。我想我应该能解决这个问题。等我还没醒过来的时候,我会看一看:)好的,我想好了。只需将实际字符串添加到$compile内的元素声明中,就像您暗示的
<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>
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);
}
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;
        });
      }
    };
  });
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;
        });
      }
    };
  });