【问题标题】:how do you re-use templates in angularjs你如何在 angularjs 中重用模板
【发布时间】:2016-02-02 20:29:49
【问题描述】:

如何重复使用模板?考虑以下 javascript 对象:

{
    MyName: '',
    Address: {
        Street: ''
    },
    MyEmployer: {
        CompanyName: '',
        Address: {
            Street: ''
        }
    }
}

还有/templates/myTemplate.html的模板文件:

<div ng-app="someapp" ng-controller="somecontroller">
    MyName: <input type="text" ng-model="MyName" />

    <div ng-include="'/templates/address.html'"></div>

    My Company: <input type="text" ng-model="MyEmployer.CompanyName" />

    <div ng-include="'/templates/address.html'"></div>
</div>

这是我想象的/templates/address.html 地址模板文件的样子:

<div>
    Street: <input type="text" ng-model="Street" />
</div>

如您所见,我正在尝试在此处重新使用地址模板。那么如何将正确的对象传递给这个模板呢?

【问题讨论】:

    标签: javascript angularjs templates


    【解决方案1】:

    回答 我自己设法解决了这个问题,并想在此处发布它,以供下一个可能正在寻找相同款待的人使用。

    我的解决方案

    在我的 OP 中,我有一个带有两个地址的模型对象,一个用于该人的家,另一个用于他/她的雇主。所以在/templates/address.html处采用相同的对象模型和相同的地址模板,我们可以添加两个额外的控制器:

    app.controller('personAddressController', ['$scope', function($scope) {
       $scope.Street = function(newValue) { return arguments.length ? model.Address.Street = newValue : model.Address.Street; }
    }]);
    app.controller('companyAddressController', ['$scope', function($scope) {
       $scope.Street = function(newValue) { return arguments.length ? model.MyEmployer.Address.Street = newValue : model.MyEmployer.Address.Street; }
    }]);
    

    以及ng-include 用于我们的地址模板:

    <div ng-include="'/templates/address.html'" ng-controller="personAddressController"></div>
    
    <div ng-include="'/templates/address.html'" ng-controller="companyAddressController"></div>
    

    另外我们需要修改我们的地址模板:

    <div>
        Street: <input type="text" ng-model="Street" ng-model-options="{ getterSetter: true }" />
    </div>
    <!--or add a form if you have more fields like i did-->
    <form ng-model-options="{ getterSetter: true }">
        <div>
            Street: <input type="text" ng-model="Street" />
        </div>
    </form>
    

    有关ng-model-options 和setter/getter(页面底部)的更多信息:https://docs.angularjs.org/api/ng/directive/ngModel

    虽然在添加表单时要小心,因为enter 键默认会进行提交,但如果您愿意,您可以轻松控制。

    最后,您可以使用指令来完成所有这一切,正如有人已经建议的那样,但您最终会使用 angular 指令作为控制器,并且根据 angular,它们并不适用于此,更多信息请参见:AngularJS - Directives vs Controllers

    【讨论】:

      【解决方案2】:

      ng-include 共享相同的控制器和相同的数据。

      因此,一个解决方案可能是考虑其他事情。也许是一个模板指令。您可以向其传递模板以及不同的值。

      // Directive
      app.directive('addressTemplate', function() {
          return {
              templateUrl: '/templates/address.html',
              scope: {
                  street: '='
              }
          };
      });
      
      // My template
      <address-template street="MyEmployer.Address.Street"></address-template>
      
      // Template
      <div>
          Street: <input type="text" ng-model="street" />
      </div>
      

      【讨论】:

      • 好吧,如果是这样的话,我就不会使用 Angular。任何 UI 框架都应该促进代码重用,这松散地意味着模板重用。这里knockoutjs.com/documentation/template-binding.html
      • 好吧,我刚刚创建了一个可以使用和修改的自定义指令,但是我想尽可能多地重用我的代码。
      • @Hani:每次您必须为可重用项目包装异步调用时,您都必须将其包装在指令中。像 ionic 这样的框架定义了很多通用指令。
      • 如果你不知道如何构建它们以及如何使用它们,你最终会得到数百个指令。指令可以非常灵活,并且是适用于任何目的的好工具。无需侮辱我的榜样。我只是想帮助您并为您提供更多选择:)
      • @Histro 此外,我的 OP 只是一个虚拟示例。为了重用各种模板,我最终会编写数百个指令,因为我有数千个具有各种属性名称的域对象。我怀疑应该是这样吗?
      【解决方案3】:

      在解决这个问题几个月后,我现在使用这种方式来避免模板重复:

      在控制器中:

      $scope.myelement = {...};
      $scope.myelements = [{ ...}, { ... }]
      

      在模板 myelement.html 中:

      {{ myelement.name }} {{ myelement.anything }}
      

      在模板中:

      <div ng-include="'myelement.html'"></div>  <!-- $scope.myelement is used --> 
      <div ng-repeat="myelement in myelements track by $index"></div> <!-- $scope.myelements[$index] used myelements.length times --> 
      

      如果你想指定另一个变量,你可以这样做:

      <div ng-include="'myelement.html'" ng-init="myelement = SomeScopeVariable;"></div>
      

      但在这种情况下,只有在编译 ng-include 时才会调用 ng-init。而且您将无法更改其中的“myelement”,您只能修改其属性。我不建议使用 ng-init,除非您只想修改/可视化控制器中的特定元素。如果您想删除它或创建另一个,请不要使用 ng-init。

      【讨论】:

      • 一些事情。首先,我不想为任何类型的数组重复模板。其次,使用ng-init 需要在模板中硬编码变量名,这违背了重用它的目的。本质上,我希望有类似 KnockoutJS 所做的事情:模板选项!
      • @Hani:在你的代码中有一个错误:你总是写 ng-model="MyName" 等等...但它应该是 ng-model="myelement.MyName"
      • MyName 是 $scope 对象的属性,但如果 myelement.MyName 是 $scope 对象的一部分,那么您将按照您的建议进行操作。
      • @Hani:您不必将对象直接存储在 $scope 中,而是存储在 $scope 的属性中,例如 $scope.myelement。通过这样做,您可以轻松地在项目的不同部分重用模板。另一个提示:在 ng-model 中,如果你没有点“。”是你做错了。
      猜你喜欢
      • 1970-01-01
      • 2014-05-08
      • 1970-01-01
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-17
      • 1970-01-01
      相关资源
      最近更新 更多