Good day.

There is a two-dimensional array, for example, people, the number and names of the fields, the number of entries are unknown. He came, for example, from here.

$scope.people = []; $http.get("grid.json").then(function(response) { $scope.people = response.data; } 

I want to make a combo box filled with all the values ​​of a two-dimensional people array along the i-th field. How to do it? I can not figure out how to do this in the methodology Angulyara. Those. there must be something like that

 Name FamilyName Вася Петров Ваня Сидоров 

Next to or instead of "Name" appears combobox with the values ​​"Vasya" and "Vanya", on "FamilyName" - "Petrov" and "Sidorov". Something like that

 <tr> <th>Name <select> <option>Вася</option> <option>Ваня</option> </select> </th><th>FamilyName <select> <option>Петров</option> <option>Сидоров</option> </select> </th></tr> 

Specification: the values ​​in the combo box must be unique. Ie, for example, if the value "Vasya" in the 0th field is repeated more than once, in the combo box it should appear once.

UPD

JSON example

 [ {"Name": "Вася", "FamilyName": "Петров"}, {"Name": "Ваня", "FamilyName": "Сидоров"} ] 
  • How this question differs from this one: Grid construction and field names - Grundy
  • I will reformulate the question - user211576
  • What combo boxes mean? html-select or from some library? - Grundy
  • besides: the object is not an array, it does not have the ith field, but if there are other arrays inside one array, then the task is trivial - Grundy
  • yes, normal selects - user211576

1 answer 1

Since the data that needs to be displayed in the same selection is in different objects, it is necessary to first prepare for the output.

It is necessary to regroup the original array so that the field name matches the list of values ​​that can be passed to the select.

You can group it like this:

 $scope.result = $scope.people.reduce(function(acc,people){ return Object.keys(people).reduce(function(acc,field){ if(!acc[field])acc[field] = []; acc[field].push(people[field]); return acc; },acc); },{}); 

In this case, the values ​​of the fields can be repeated, since uniqueness is not checked. to save only unique values ​​instead of an array, you can add them to an object; object keys are unique, for example:

 $scope.result = $scope.people.reduce(function(acc,people){ return Object.keys(people).reduce(function(acc,field){ if(!acc[field])acc[field] = {}; acc[field][people[field]]=people[field]; return acc; },acc); },{}); 

Now you can proceed to the conclusion:

 <th data-ng-repeat="(field,values) in result"> {{field}} <select data-ng-options="value for value in values" data-ng-model="selected[field]"></select> </th> 

Working example:

 angular.module('app', []) .controller('ctrl', function($scope) { var data = [{ "Name": "Вася", "FamilyName": "Петров" }, { "Name": "Вася", "FamilyName": "Сидоров" }, { "Name": "Ваня", "FamilyName": "Сидоров" }, { "Name": "Ваня", "FamilyName": "Петров" }]; $scope.selected = {}; $scope.selectedUniq = {}; $scope.result = data.reduce(function(acc, people) { return Object.keys(people).reduce(function(acc, field) { if (!acc[field]) acc[field] = []; acc[field].push(people[field]); return acc; }, acc); }, {}); $scope.resultUniq = data.reduce(function(acc, people) { return Object.keys(people).reduce(function(acc, field) { if (!acc[field]) acc[field] = {}; acc[field][people[field]] = people[field]; return acc; }, acc); }, {}); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script> <div ng-app="app" ng-controller="ctrl"> <table> <tr> <th>Не униакальные</th> <th data-ng-repeat="(field,values) in result"> {{field}} <select data-ng-options="value for value in values" data-ng-model="selected[field]"></select> </th> </tr> <tr> <th>Униакальные</th> <th data-ng-repeat="(field,values) in resultUniq"> {{field}} <select data-ng-options="value for value in values" data-ng-model="selectedUniq[field]"></select> </th> </tr> </table> <pre>{{selected|json}}</pre> <pre>{{selectedUniq|json}}</pre> </div> 

  • Not quite sure why here $ scope.result = $ scope.people.reduce (function (acc, people) {return Object.keys (people). Reduce (function (acc, field) {if (! Acc [field] ) acc [field] = []; acc [field] .push (people [field]); return acc;}, acc);}, {}); two reduce. It seems that the first one returns what is required, no? - user211576
  • @ user211576, the first one runs through people, the second one by the properties of people (first name, last name, etc.) - Grundy
  • Changed reduce a bit to make $ scope.result = $ scope.people.reduce (function (acc, people) {return Object.keys (people). reduce (function (acc, field) {if (! acc [field]) { acc [field] = [];} if (acc [field] .indexOf (people [field]) == - 1) {acc [field] .push (people [field]);} return acc;}, acc) ;}, {}); - user211576
  • @ user211576, why? if the following is an example with uniqueness without a superfluous loop oiled in indexOf - Grundy