简体   繁体   English

具有多个模板的 AngularJS 指令

[英]AngularJS directive with multiple templates

Task:任务:

  • To show contact.显示联系方式。
  • Contact is JSON data, let's say {name: "Mark", location: "England", phones: [...]}.联系人是 JSON 数据,比如说 {name: "Mark", location: "England",phones: [...]}。
  • Contact could be shown in multiple ways: compact / detailed / enhanced with additional info (shared contacts - additional directive)联系人可以通过多种方式显示:紧凑/详细/通过附加信息增强(共享联系人 - 附加指令)

Because contact could be shown on different pages in different places it's naturally to create directive (widget) for contact, but here is question: "How to organize same widget with multiple templates?"因为联系人可以在不同位置的不同页面上显示,所以很自然地为联系人创建指令(小部件),但这里有一个问题: “如何用多个模板组织同一个小部件?”

Options:选项:

  1. Create one directive with one template, that hides sections according to contact "type" - big template with possibly a lot of ng-switch and ng-if使用一个模板创建一个指令,根据联系人“类型”隐藏部分-可能有很多 ng-switch 和 ng-if 的大模板
  2. Create directive for each template - almost same directives with only different template (or templateURL)为每个模板创建指令-几乎相同的指令,只有不同的模板(或 templateURL)
  3. To load templates dynamically while linking - has problems with transclusion and replacing (merging attributes) 在链接时动态加载模板-在嵌入和替换(合并属性)方面存在问题

Whats your expirience with solving these problem?你解决这些问题的经验是什么?

Personally I think that Option 2 offers a clean separation between display modes.我个人认为选项 2 在显示模式之间提供了清晰的分离。 I have created a working CodePen example to illustrate how you might accomplish this cleanly by using separate directives for each template.我创建了一个可用的 CodePen 示例来说明如何通过为每个模板使用单独的指令来干净地完成此操作。

The method I used in my CodePen example utilizes a template factory which is injected into each directive via Angular DI.我在 CodePen 示例中使用的方法利用了一个模板工厂,该工厂通过 Angular DI 注入到每个指令中。 The template factory implementation is very clean since it merely uses ng-include template strings for each of the different supported display modes (compact & detailed).模板工厂实现非常干净,因为它仅使用ng-include模板字符串来支持每种不同的显示模式(紧凑和详细)。 The actual HTML templates (partials) can be housed in external view files or internal script blocks.实际的 HTML 模板(部分)可以存放在外部视图文件或内部脚本块中。

Using the contact directives are easy:使用联系指令很容易:

<contact compact ng-repeat="contact in contacts" ng-model="contact"></contact>

This creates a compact version of the contact list.这将创建联系人列表的紧凑版本。

<contact detailed ng-repeat="contact in contacts" ng-model="contact"></contact>

This creates a detailed contact listing.这将创建一个详细的联系人列表。

I will admit that I haven't deployed code like this to production so there may be scalability or other concerns I haven't considered.我承认我还没有将这样的代码部署到生产中,所以可能存在我没有考虑过的可扩展性或其他问题。 I hope the code I provided answers your questions or at least provides inspiration for further exploration.我希望我提供的代码可以回答您的问题,或者至少为进一步探索提供灵感。

I have build a new approach working on Adam example and using also the sample from angular docs in which they talk about functions in templateUrl property https://docs.angularjs.org/guide/directive , this is the plunker from angular docs: http://plnkr.co/edit/h2CSf2WqCLYfPvzL9WQn?p=preview我已经建立了一种处理 Adam 示例的新方法,并使用了来自 angular 文档的示例,其中他们讨论了 templateUrl 属性中的函数https://docs.angularjs.org/guide/directive ,这是来自 angular 文档的 plunker: http ://plnkr.co/edit/h2CSf2WqCLYfPvzL9WQn?p=preview

.directive('myCustomer', function() {
    return {
      templateUrl: function(elem, attr){
        return 'customer-'+attr.type+'.html';
      }
    };
  });

And this is my remixed solution:这是我重新混合的解决方案:

http://codepen.io/anon/pen/wawOyz?editors=101 http://codepen.io/anon/pen/wawOyz?editors=101

app.factory('templates', function() {
  return {
    compact:   'compact',
    detailed:  'detailed'
  };
 });

app.directive('contact', function(templates) {
  return {
    restrict: 'E',
    templateUrl: function($elem, $attr){
      return templates[$attr.mode];       
    },
    scope: {
      contact: '=ngModel'
    }
  };
});

I liked the idea of having all template addresses in one factory but I find the directive-per-mode quite repetitive and if you have several elements using this approach you will need to namespace them (contact-text, email-text, company-text) so they don't crash.我喜欢在一个工厂中拥有所有模板地址的想法,但我发现每个模式的指令非常重复,如果您有多个使用这种方法的元素,您将需要命名它们(联系文本、电子邮件文本、公司文本) 所以他们不会崩溃。

I am not sure yet if this is a better way to go, is shorter and more DRY, but maybe is more difficult to test or less customizable.我还不确定这是否是更好的方法,是否更短且更 DRY,但可能更难测试或更少可定制。 I just wanted to share the approach in case it can help anyone.我只是想分享这种方法,以防它可以帮助任何人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM