【问题标题】:AngularJS creating a directive then uses another directiveAngularJS 创建一个指令然后使用另一个指令
【发布时间】:2014-07-22 22:31:31
【问题描述】:

我正在尝试创建一个指令来减少我必须编写的样板代码。

我正在使用 angular xeditable 指令来允许内联编辑,但是当我从我的指令中添加 xeditable 指令属性时,它不起作用。

当我说它不起作用时,我的意思是通常当我单击元素时会出现一个输入框,而现在当我单击元素时什么也没有发生。

Glenn.directive('edit', function() {
    return {
        restrict: 'A',
        template: '{{ content.' + 'ParamData' + '.data }}',
        scope: {
            ParamData: '@edit'
        },
        link: function(scope, element, attrs) {     
            element.attr('editable-text', 'content.' + attrs.edit + '.data');
            element.attr('onbeforesave', 'update($data, content.' + attrs.edit +'.id');
        }
    }
});

所以,我的第一个问题是 xeditable 指令不起作用,因为它在我的内部。我是创建 angularjs 指令的新手,但我想知道它是否与它的编译方式有关?

我的第二个问题是模板。如果我的模板看起来像这样

template: '{{ ParamData }}'

然后它会输出正确的数据,但是如果没有其他部分来引用范围数据,我就无法使其工作。

另外,这是使用指令时的视图

<h2 edit="portrait_description_title"></h2>

如果我不使用指令来减少锅炉代码,这就是它的样子

<h1 editable-text="content.portrait_description_title.data" onbeforesave="update($data, content.portrait_description_title.id)">
     {{ content.portrait_description_title.data }}
</h1>

感谢您的建议!

【问题讨论】:

  • 您需要阅读范围和嵌入。当您指定 scope: {} 时,您正在创建一个新范围,这就是您无法访问父范围的原因。要么不创建子范围,要么像使用 ParamData 一样传入所需的元素。使用嵌入来嵌套指令(例如,类似于 ng-repeat 的工作方式)。
  • 要么您需要重新编译代码,要么(如上所述)使用嵌入,编译器将确保处理嵌套指令编译。

标签: javascript angularjs angularjs-directive


【解决方案1】:

你必须在添加这些属性后重新编译元素,这里是一个例子:

示例插件: http://plnkr.co/edit/00Lb4A9rVSZuZjkNyn2o?p=preview

.directive('edit', function($compile) {
  return {
    restrict: 'A',
    priority: 1000,
    terminal: true, // only compile this directive at first, will compile others later in link function
    template: function (tElement, tAttrs) {
      return '{{ content.' + tAttrs.edit + '.data }}';
    },
    link: function(scope, element, attrs) {
      attrs.$set('editable-text', 'content.' + attrs.edit + '.data');
      attrs.$set('onbeforesave', 'update($data, content.' + attrs.edit + '.id)');
      attrs.$set('edit', null); // remove self to avoid recursion.
      $compile(element)(scope);
    }
  }
});

需要考虑的事项:

  • 删除隔离范围以简化操作,因为您似乎希望首先直接绑定到控制器 content.portrait_description_title.data 中的范围。
  • template:也接受函数,这样就可以获取edit的属性值来构造模板。
  • 标记为terminal 指令并引发priority,这样在第一次运行时,只有这个指令(在同一元素中的其他指令中)会被编译。
  • attrs.$set() 可用于添加/删除属性,使用它来添加 editable-text 指令和 onbeforesave
  • 删除指令本身,即edit 属性,以防止下次编译后出现递归。
  • 使用$compile服务重新编译元素,以使editable-textonbeforesave工作。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    只需在第一个指令的模板内添加另一个指令并将其绑定到您从 attr 获得的作用域模型。您还可以添加控制器功能,并创建更多模型,或逻辑并绑定到指令模板。

    另外,您的属性可能在模板上不可用,而不是您需要将 $watch 添加到您的隔离范围模型并更新控制器内的另一个范围模型。第二个模型需要绑定到模板。您可以在 AngularJS 文档上找到有关指令的更多信息,但这里有一篇很好的文章,它可以帮助您:

    http://www.sitepoint.com/practical-guide-angularjs-directives-part-two/

    【讨论】:

      猜你喜欢
      • 2014-02-14
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 2016-09-26
      • 1970-01-01
      • 2012-12-16
      • 1970-01-01
      • 2017-04-12
      相关资源
      最近更新 更多