【问题标题】:Variable directive name in angular角度变量指令名称
【发布时间】:2015-04-02 00:47:21
【问题描述】:

我确定以前有人问过这个问题,但是很难提出问题,因此也很难搜索...

我的一个应用程序使用了几个第三方指令之一。目前,我正在处理的指令是 xeditable 库中的指令,但这个问题不仅仅是关于那个库,因为我之前遇到过这种需求。

目前,我的代码如下所示:

<div ng-switch on="editTypeNeeded">
    <div ng-switch-when="textarea" editable-textarea="myVar" onbeforesave="doBeforeSaveStuff($data)" class="whatever" ng-class="whatever2()" ng-mouseover="doStuff()" some-other-directive="doMoreStuff()">
        {{myvar}}
        ...
        and other stuff
    </div>
    <div ng-switch-when="textfield" editable-text="myVar" onbeforesave="doBeforeSaveStuff($data)" class="whatever" ng-class="whatever2()" ng-mouseover="doStuff()" some-other-directive="doMoreStuff()">
        {{myvar}}
        ...
        and other stuff
    </div>
    <div ng-switch-when="checkbox" editable-checkbox="myVar" onbeforesave="doBeforeSaveStuff($data)" class="whatever" ng-class="whatever2()" ng-mouseover="doStuff()" some-other-directive="doMoreStuff()">
        {{myvar}}
        ...
        and other stuff
    </div>
    <div ng-switch-when="date" editable-bsdate="myVar" onbeforesave="doBeforeSaveStuff($data)" class="whatever" ng-class="whatever2()" ng-mouseover="doStuff()" some-other-directive="doMoreStuff()">
        {{myvar}}
        ...
        and other stuff
    </div>
    ...
    etc...
</div>

当每个switch 选项之间发生变化的唯一是“editable-textarea”、“editable-text”等时,这是大量的代码重复。

我想要的是将以上所有内容替换为以下内容:

<div {{directiveName}}="myVar" onbeforesave="doBeforeSaveStuff($data)" class="whatever" ng-class="whatever2()" ng-mouseover="doStuff()" some-other-directive="doMoreStuff()">
    {{myvar}}
    ...
    and other stuff
</div>

这显然是行不通的,但必须有一种方法来做这样的事情......


更新:

我最终使用了选定的答案,但稍作修改以允许变量指令名称和指令值。像这样:

.directive('useDirective', function ($compile) {
    return {
        restrict: 'A',
        link: function (scope, elem, attrs) {
            attrs.$observe('useDirective', function(directiveNameAndValue) {
                if (directiveNameAndValue) {
                    var nameAndValue = directiveNameAndValue.split('='),
                        dirName = nameAndValue[0],
                        value = nameAndValue[1] || '';
                    elem.attr(dirName, value);
                    elem.removeAttr('use-directive');
                    $compile(elem)(scope);
                }
            });
        }
    };
});

我是这样使用它的:

<div use-directive="{{getDirectiveType(value)}}=value" class="pointer" onbeforesave="notifyOfChange($data)">{{value}}</div>

Plunker 示例:http://plnkr.co/edit/JK5TkFKA2HutGJOrMo8a?p=preview


更新 2:
我发现上述技术似乎不能很好地与 angular-animate.js 库配合使用。它会导致该库多次引发以下错误:

 TypeError: Cannot read property 'parentNode' of undefined
     at angular-animate.js:1203
     at angular-animate.js:539
     at n.$digest (angular.js:14358)
     at n.$apply (angular.js:14571)
     at angular.js:16308
     at e (angular.js:4924)
     at angular.js:5312

不过,页面似乎仍然可以正常工作。

【问题讨论】:

  • 编写自己的指令来体现上述所有逻辑?
  • 我不明白为什么您不能将该开关逻辑粘贴到指令的模板中,然后在指令上为 editTypeNeed 传递或设置一个属性。将所有 HTML 保留在指令中,并在表单中使用指令来保持整洁。

标签: angularjs


【解决方案1】:

你可以创建一个指令来统治他们:

<div lord-of-the-directives="{{directiveName}}">

会是这样的

module.directive('lordOfTheDirectives', function ($compile) {
  return {
    restrict: 'A',
    link: function (scope, elem, attrs) {
      attrs.$observe('lordOfTheDirectives', function(dirName) {
        if (dirName) {
          elem.append('<div ' + dirName + '>');
          $compile(elem)(scope);
        }
      });
    }
  };
});

(未经测试,但就是这样)

更新在评论中请求,以保持元素原样(及其类和东西):

module.directive('lordOfTheDirectives', function ($compile) {
  return {
    restrict: 'A',
    link: function (scope, elem, attrs) {
      attrs.$observe('lordOfTheDirectives', function (dirName) {
        if (dirName) {
          elem.attr(dirName, '');
          elem.removeAttr('lord-of-the-directives');
          $compile(elem)(scope);
        }
      });
    }
  };
});

【讨论】:

  • 我喜欢这个主意...当你的 div 有一堆其他属性并且看起来更像这样时,有没有办法让它工作:&lt;div lord-of-the-directives="{{directiveName}}" class="whatever" ng-class="whatever2()" ng-mouseover="doStuff()" some-other-directive="doMoreStuff()"&gt;{{myVar}}&lt;/div&gt;?还是lordOfTheDirectives 不接受任何属性,所有额外的属性/指令都需要从lordOfTheDirectives 中添加,而不是传入 的想法?
  • 是的,您可以直接将其名称添加到元素并重新编译整个内容,而不是 附加 新指令。我已经用这种方法更新了我的答案。请注意,我删除了 lord 指令,以免两个活动相互混淆:这成为一次性指令。如果这不是您想要的,您可以保留 lord-of-the-dirctives 属性并在添加新指令之​​前删除之前的指令。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
  • 2015-01-13
  • 2016-05-04
  • 1970-01-01
  • 2014-12-29
  • 1970-01-01
相关资源
最近更新 更多