繁体   English   中英

级联父子项从动态JSON数据中选择框

[英]Cascading parent child select boxes from dynamic JSON data

我已经从JSON数据动态创建了一些链式选择框,我将从服务器收到这些数据。 链接/级联的工作方式是每个选择框都是具有以下属性的命名对象:

  1. 父属性:作为此选择框对象的父对象的对象的名称。
  2. 选项:选项对象的数组,其中每个对象包含:(a)选项值(b)父选项值 - 用于映射当前值的父选择框值。 (c)选项ID。

  3. 选定选项:具有两个属性的对象:(a)当前选定的值(b)当前所选值的ID。

我在“选项”标签中使用ng-repeat创建选择框,或者在“select”标签中使用ng-option,然后我使用自定义过滤器,我通过匹配父选项值来过滤检索到的选项(2) (2> b)选项值(2> a)与其父对象的“当前选择值”(3> a)。 基本上使用自定义过滤器从子选项值到选定父值进行多对一映射。

在此输入图像描述

我能够正确映射父子选择框,但问题是当我更改父选择框值时,其子对象的“选定选项值”不会更新( 子选择的项目不会抓取筛选列表中的第一项,导致孙子下拉不更新。[1]

有没有办法,如果父值更改,子选择框(以及后续的子/孙)使用第一个选项值而不是当前空白值初始化?

这是工作的plunker。 (ng-repeat实施)。 真的很感激任何帮助。

这是另一个带有ng-options实现的plunker

HTML(ng-repeat):

<div ng-repeat="selection in vm.selectionData">
    <div ng-repeat="(key, attribute) in selection.attributes">
      <span>{{key}}</span>
      <select class="form-control" ng-model="attribute.selectedOption.name">
        <option ng-repeat="option in attribute.options | optionFilter : selection.attributes[attribute.parentAttr]">{{option.name}}</option>
      </select>
    </div>
</div>

HTML(ng-options):

<div ng-repeat="selection in vm.selectionData">
    <div ng-repeat="(key, attribute) in selection.attributes">
      <span>{{key}}</span>
      <select ng-model="attribute.selectedOption" ng-options="attribute.name for attribute in (attribute.options | optionFilter : selection.attributes[attribute.parentAttr]) track by attribute.id">
      </select>
    </div>        
</div>

JS:

myApp.filter('optionFilter', function() {
  return function(items, parent) {
    var result = [];
    if (parent) {
      for (var i = 0; i < items.length; i++) {
        console.log(items[0].parent, parent.selectedOption.name);
        if (items[i].parent === parent.selectedOption.name) {
          result.push(items[i]);
        }
      }
      return result;
    } else {
      return items;
    }
  }
});

myApp.controller("MyCtrl", function($scope) {

  this.selectionData = [{
    selectionType: "Geography",
    attributes: {
      country: {
        parentAttr: "none",
        options: [{
          name: "India",
          parent: "None",
          id: 1
        }, {
          name: "Bangladesh",
          parent: "None",
          id: 2
        }, {
          name: "Afganistan",
          parent: "None",
          id: 3
        }],
        selectedOption: {
          name: "India",
          id: 1
        }
      },
      state: {
        parentAttr: "country",
        options: [{
          name: "Rajasthan",
          parent: "India",
          id: 1
        }, {
          name: "Haryana",
          parent: "India",
          id: 2
        }, {
          name: "Dhaka",
          parent: "Bangladesh",
          id: 3
        }, {
          name: "Kabul",
          parent: "Afganistan",
          id: 4
        }],
        selectedOption: {
          name: "Rajasthan",
          id: 1
        }
      },
      city: {
        parentAttr: "state",
        options: [{
          name: "Kota",
          parent: "Rajasthan",
          id: 1
        }, {
          name: "Sirsa",
          parent: "Haryana",
          id: 2
        }, {
          name: "Alwar",
          parent: "Rajasthan",
          id: 3
        }, {
          name: "Gurgaon",
          parent: "Haryana",
          id: 4
        }, {
          name: "Kabul",
          parent: "Kabul",
          id: 5
        },{
          name: "Dhaka",
          parent: "Dhaka",
          id: 6
        }
        ],
        selectedOption: {
          name: "Kota",
          id: 1
        }
      }
    },
  }];

});

参考文献:

经过一段时间的努力,我想出了一个解决方案(虽然不确定它是否符合最佳实践)。 在我的自定义过滤器中,它根据父对象的选定选项值返回已过滤的选项,我另外发送当前的选择框对象。 然后,

  1. 过滤器首先检查父对象是否存在,否则返回所有选项。
  2. 如果父存在,则它循环遍历当前选择框对象的所有可用选项。
  3. 如果当前选择框选项的父值与父对象的选定选项值匹配,则仅当父对象的选定选项不为空时 ,它才会推送结果数组中的已过滤选项值(当祖父项值更改时,父对象的选定选项可以为空和父级不会抓取结果筛选的选项,导致父选择框中的空白第一个选项)。 这将暂时导致当前选择框完全为空,因为父对象的selected选项为null。
  4. 然后,它检查当前选择框对象的选定选项是否为空。 如果是这样,它将结果数组的第一个元素(对象)分配给选定的选项对象,并返回结果数组。 由于过滤器将针对所有选择框(祖父,父和子)运行,因此它会将父过滤数组中的第一个元素设置为父对象的选定选项。 现在,当父对象的selected选项不再为null时,当前选择框将显示已筛选的选项(来自结果数组),结果数组的第一个元素将分配给当前选择框的选定选项。

在这里工作演示。 请分享是否有更好的解决方案。 以下是自定义过滤器:

myApp.filter('optionFilter', function() {
  return function(items, parent, self) {
    var result = [];
    if (parent) {
      for (var i = 0; i < items.length; i++) {
        if (parent.selectedOption !== null && items[i].parentValue === parent.selectedOption.value) {
          result.push(items[i]);
        }
      }
      if (self.selectedOption === null) {
        self.selectedOption = result[0];
      }
      return result;
    } else {
      return items;
    }
  }
});

HTML:

<div ng-repeat="(key, item) in data">
    <span>{{key}}</span>
    <select ng-model="item.selectedOption" ng-options="option.value for option in (item.availableOptions | optionFilter : data[item.parent] : item) track by option.id">
    </select>
</div>

数据:

this.data = {
  Country: {
    parent: "None",
    availableOptions: [{
      value: "United States",
      parentValue: "None",
      id: 1
    }, {
      value: "China",
      parentValue: "None",
      id: 2
    }, {
      value: "India",
      parentValue: "None",
      id: 3
    }],
    selectedOption: {
      value: "United States",
      parentValue: "None",
      id: 1
    }
  },
  State: {
    parent: "Country",
    availableOptions: [{
      value: "California",
      parentValue: "United States",
      id: 1
    }, {
      value: "Shanghai",
      parentValue: "China",
      id: 2
    }, {
      value: "Delhi",
      parentValue: "India",
      id: 3
    }],
    selectedOption: {
      value: "California",
      parentValue: "United States",
      id: 1
    }
  },
  City: {
    parent: "State",
    availableOptions: [{
      value: "Greenfield",
      parentValue: "California",
      id: 1
    }, {
      value: "Shanghai",
      parentValue: "Shanghai",
      id: 2
    }, {
      value: "New Delhi",
      parentValue: "Delhi",
      id: 3
    }],
    selectedOption: {
      value: "Greenfield",
      parentValue: "California",
      id: 1
    }
  }
};

暂无
暂无

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

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