AngularJS:对表单进行组件化

时间:2014-10-20 13:59:38

标签: angularjs oop design-patterns

我有两种形式在视觉上90%相同,并且表单的支持代码是90%相同。因此,我在两者之间有 90%重复代码,我想消除它。

在我的设置中,我有一个模型,其他两个模型扩展。表单(视图)只是这些模型的投影,它们的输入元素映射到每个模型的字段。

画报:

 ____________________________
|          Base Model        |
------------------------------
      |                |
      |                |
 _____________    _____________
| Sub Model A |  | Sub Model B |
---------------  ---------------
      |                |
      |*projected with*|
 _____________    _____________
| Form A      |  | Form B      |
---------------  ---------------

正如我之前提到的,模型A和B大约相同(这就是为什么它们从基础模型开始继承)。这些模型实现了方法save()load()destroy(),它们会自动与我的后端通信,以正确更新所表示对象的持久状态。

模型A和B每个都有一个控制器,它实现了修改模型数据的方法。模型A有一个控制器,模型B有一个控制器 - 这些控制器与模型非常相似,90%相同。这些控制器驱动表单的核心功能(诸如设置下拉列表,获取其他数据,初始化点击处理程序等等)。它们每个都实现save(),只需在相应的模型上调用save()方法。

重申一下,我的问题是 90%的代码是重复的,因为这两个模型的90%是相同的

简短示例:

说我有一个输入元素组有两个输入:First NameLast Name。还假设我想检查我的数据库以确保Last Name值已存在。

模型A的save()方法将:

  • 检查数据库中的Last Name值,如果不存在则创建
  • 将名称另存为<First Name> <Last Name>

模型B的save()方法将:

  • 检查数据库中的Last Name值,如果不存在则创建
  • 将名称另存为<Last Name>, <First Name>

现在我在Last Name的查找或创建中有重复的代码。随着更大和更复杂的表单字段,此代码重复变得失控。这甚至不考虑控制器,它们也有重复的代码,可以为Last Name输入设置自动完成预先输入框。

还有多种类型的重叠:

  1. 上述情况,其中模型是相同的字段名称,但可以进行格式化和处理不同
  2. 其中一个模型具有另一个模型不
  3. 的字段
  4. 两个模型具有相同的字段并以相同的方式处理
  5. 我最初的尝试,最终失败了,就是为表单的每个组件创建一个视图和控制器。我有两个主要视图(每个模型一个)使用ng-include来包含每个表单组件。 ng-include将指定实现save()load()的控制器,父控制器将调用该控制器。

    示例:

    <ng-include
      src="'app/forms/name.htm'"   <--- view HTML for the name component
      ng-controller="FormNameController"   <--- controller for the name component
    ></ng-include>
    

    我的想法是让每个组件控制器实现:

    • 知道如何保存其所知信息的save()方法
    • 知道如何加载需要知道的信息的load()方法

    然后我会使用整个页面的控制器来调用所有组件控制器的save()load()方法。

    这种方法有两个主要问题(在许多小问题中):

    1. 我无法找到让父控制器自动意识到组件控制器存在的优雅方法。 broadcastemiton似乎有一些奇怪的方法,但它似乎非常hacky(因为我还需要save()load()方法在组件控制器上返回promises
    2. 让(多个)组件控制器自行保存/加载数据,然后让它们更新主控制器支持的模型,这很麻烦
    3. 由于我正在使用框架(AngularJS),我认为有某种类型的&#34; Angular&#34;有效地做到这一点的方法。我花了很长时间环顾四周寻找一个很好的方法,但找不到任何东西。

      任何帮助,输入或推动正确的方向都将非常感激。我不确定是在这里发布还是在programmers.stackexchange.com上发布;希望这是正确的地方。

1 个答案:

答案 0 :(得分:0)

Angular的方法是使用服务。 您可以将大部分控制器逻辑分解为服务,以保持控制器清洁并保持代码可重用。

例如,

并且不会过多地假设您的实现。

app.factory('baseService', [function(){
  var base = {};
  base.save = function(data){
    //persist data      
  };    
  base.findOrCreate = function(value){
    //...
  }
  return base;
}]);

app.factory('aService', ['baseService', function(baseService){
  var a = {};
  a.save = function(aModel){
    baseService.findOrCreate(aModel.lastName);
    //do something
    baseService.save(aModel);
  };
  return a;
}]);

app.controller('aController', ['$scope', 'aService', function($scope, aService){
  //...
  $scope.save() = function(){
    //...
    aService.save($scope.aModel);
  };
}]);