使用两个数据源呈现指令

时间:2015-11-27 20:46:15

标签: javascript angularjs json angularjs-directive

我的问题有点复杂,所以我会尽量详细解释。

我在SPA中有一个指令,它基于我从API获得的JSON数据来呈现它们的组件。基于元素及其类型(JSON是一个不同对象的数组),我将渲染特定指令中的每个对象:

  • 对象类型1:在指令类型1中呈现。
  • 对象类型2:在指令类型2中呈现。
  • 对象类型3:在指令类型3中呈现。

指令类型1-2-3包含在父指令中,每个指令都有不同的控件(select,checkbox)。这是一个非常简单的草图:

Parent Directive and Directives Type 1-2-3

和“子指令”:

Sub-directive

我正在按以下方式渲染我的元素(Container directive):

<div ng-repeat="element in elementList | customFilter:itemsType1">
  <div class="line"></div>

  <div class="form-group">
    <directivetype1 itemdata="element" modeldata="data"></directivetype1>
  </div>
</div>

<div ng-repeat="element in elementList | customFilter:itemsType2">
  <div class="line"></div>

  <div class="form-group">
    <directivetype2 itemdata="element" modeldata="data"></directivetype2>
  </div>
</div>
...

这是Directive 1代码:

<div class="container-fluid">
  <div class="form-group">
    <div class="col-xs-6 col-sm-3">
      <div class="checkbox">
        <label><input type="checkbox"/>{{itemdata.metadata.description}}</label>
      </div>
    </div>

    <div class="col-xs-6 col-sm-3">
      <label>Option</label>
      <select class="form-control" ng-model="" ng-options="list.id as list.label for list in item.optionData"></select>
    </div>
  </div>
</div>

当我尝试将模型附加到呈现的每个元素时,我的问题就出现了,因为:

  1. 模型数据来自另一个API,在另一个结构中。
  2. 我正在使用ng-repeat迭代控件列表,但是,当我将模型数据传递给子指令时,我传递了所有可能的数据(作为数组)并且我无法过滤并知道该数组中的哪个对象属于特定的视图元素。
  3. 数据具有以下结构:

    查看数据:

    [
        {
            "elementA": {
                "metadata": {
                    "id": "001",
                    "subId": "016",
                    "description": "Element 1"
                },
                "optionData": [
                    {
                        "id": "5",
                        "label": "Option 1"
                    },
                    {
                        "id": "6",
                        "label": "Option 2"
                    },
                    {
                        "id": "7",
                        "label": "Option 3"
                    }
                ]
            }
        },
        {
            "elementB": {
                "metadata": {
                    "id": "002",
                    "subId": "024",
                    "description": "Element 2"
                },
                "optionData": [
                    {
                        "id": "1",
                        "label": "Option 1"
                    },
                    {
                        "id": "2",
                        "label": "Option 2"
                    },
                    {
                        "id": "3",
                        "label": "Option 3"
                    }
                ]
            }
        }
    ]
    

    模型数据:

    [
        {
            "metadata": {
                "id": "002",
                "subId": "024",
                "description": "Element 2",
                "selected": "1"
            },
            ...(Some other data belonging to the model)
        },
        {
            "metadata": {
                "id": "001",
                "subId": "016",
                "description": "Element 1",
                "selected": "5"
            },
            ...(Some other data belonging to the model)
        },
        ...
    ]
    

    正如您所看到的,关联这两种模型的唯一方法是使用id对象中的subIdmetadata字段(因为metadata本身可能会有更多变化或更少的领域)。

    问题

    如何基于视图对象过滤我的模型对象?我的目标是获取与视图对象相关的模型对象,并将其传递给子指令,以将其设置为我在该点渲染的控件的模型。

    修改

    正如cmw指出的那样,我编写了一个函数来将每个模型对象与它们各自的视图对象相关联,但该对象没有反映在指令范围内。 itemdatamodeldata使用双向范围('=')传递给指令。我认为(但我不完全确定)当我将函数传递给modeldata时,该指令无法设置返回的对象。我根据cmw答案编写的解决方案如下:

    指令:

    <directivetype1 itemdata="element" modeldata="getModelObject(data)"></directivetype1>
    

    JS(在父级的Ctrl中编码):

    $scope.getModelObject = function(element){
      var id = typeof element.metadata === 'undefined' ? null : element.metadata.id;
      var subid = typeof element.metadata === 'undefined' ? null : element.metadata.subid;
      var modelElement = null;
    
      for (var i = 0; i < $scope.data.length; i += 1){
        element = $scope.data[i];
        if (modelElement.metadata.id === id && modelElement.metadata.subid === id) return element;
      }
    
      return null;
    };
    

    但是当我尝试使用modeldata在指令中工作时,我在FF / Chrome控制台中看到“null”。

    知道发生了什么的任何准则?

    感谢。

    编辑2:

    我在这里添加了我的代码版本:http://plnkr.co/edit/xjp1l3PuWczdqYf5LP8q?p=preview。可悲的是,在Plunkr中它按预期工作但我的代码没有(我期望看到<h1>{{modeldata}}</h1>的输出)。我正在比较两个版本以查看任何差异(请注意,我已经包含了我在项目中使用的相同AngularJS版本。)

1 个答案:

答案 0 :(得分:0)

正如您所指出的,我认为关键是只使用id对象上的subIdmeta属性。

这样的事可能有用......

<div ng-repeat="element in elementList | customFilter:itemsType1">
  <div class="line"></div>

  <div class="form-group">
    <directivetype1 itemdata="element" modeldata="modelDataFor(element)">
    </directivetype1>
  </div>
</div>

然后,在您的控制器中,定义如下的函数......

$scope.modelDataFor = function (element) {
  var id    = element.meta.id,
      subId = element.meta.subId,
      curr;

  for (var i = 0; i < $scope.data.length; i += 1) {
    curr = $scope.data[i];
    if (curr.meta.id === id && curr.meta.subId === subId) {
      return curr;
    }
  }

  return null;
}

这似乎是将相关数据模型对象传递到嵌套指令的最自然的地方。