Как реализовать Excel Как фильтр в angularjs?

Мне нужно реализовать простой Excel Like Filer для таблицы, используя angulajs (v.1). Я застрял, пожалуйста, помогите мне, я добавил свой фрагмент кода ниже. Я хочу показать фильтрованные данные в таблице после проверки флажка и нажать кнопку "ОК". Я делаю это с использованием модели, но не получаю решения, как я могу это достичь?

var myApp = angular.module('myApp', [])
myApp.filter('unique', function () {

    return function (arr, field) {
        var o = {}, i, l = arr.length, r = [];
        for (i = 0; i < l; i += 1) {
            o[arr[i][field]] = arr[i];
        }
        for (i in o) {
            r.push(o[i]);
        }
        return r;
    };
})
  
      .controller('employeeController', function ($scope) {
     
   var employees = [{
    "Name": "Alfreds Futterkiste",
    "City": "Berlin",
    "Country": "Germany"
  }, {
    "Name": "Berglunds snabbköp",
    "City": "Luleå",
    "Country": "Sweden"
  }, {
    "Name": "Blauer See Delikatessen",
    "City": "Mannheim",
    "Country": "Germany"
  }, {
    "Name": "Blondel père et fils",
    "City": "Strasbourg",
    "Country": "France"
  }, {
    "Name": "Bólido Comidas preparadas",
    "City": "Madrid",
    "Country": "Spain"
  }, {
    "Name": "Bon app'",
    "City": "Marseille",
    "Country": "France"
  }, {
    "Name": "Bottom-Dollar Marketse",
    "City": "Tsawassen",
    "Country": "Canada"
  }, {
    "Name": "Cactus Comidas para llevar",
    "City": "Buenos Aires",
    "Country": "Argentina"
  }, {
    "Name": "Centro comercial Moctezuma",
    "City": "México D.F.",
    "Country": "France"
  }, {
    "Name": "Chop-suey Chinese",
    "City": "Bern",
    "Country": "Switzerland"
  }, {
    "Name": "Comércio Mineiro",
    "City": "São Paulo",
    "Country": "Canada"
  }];
      $scope.employees=employees;
      
    
})
.changeType {
        background: #eee;
        border-radius: 2px;
        border: 1px solid #bbb;
        color: #bbb;
        font-size: 10px;
        line-height: 9px;
        padding: 4px;
        float: right;
    }

        .changeType:before {
            content: "\25BC ";
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="#" onclick="location.href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'; return false;" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script>
 $(document).on('click', '#tblbatch .dropdown-menu', function (e) {
        e.stopPropagation();
    });
    </script>
<body ng-app="myApp">
    <div ng-controller="employeeController">
        <div class="container" style="margin-top:40px;">
            <div class="row">
                {{error}}
                <div class="col-md-6">
                    <table class="table table-bordered table-condensed" >
                        <thead>
                            <tr>
                                <th>Country
                                <div class="dropdown" style="float: right">
                                        <button id="btnSearchBatch" class="changeType dropdown-toggle" ng-click="getAllBatchID()" type="button" data-toggle="dropdown"></button>
                                        <div class="dropdown-menu prop" aria-labelledby="btnSearchBatch" style="width: 250px; padding: 15px;">
                                            <div class="col-md-12" style="padding: 0;">
                                                <table style="width:100%">
                                                    <tr>
                                                        <th style="text-align: left">
                                                            <form class="" role="form">
                                                                Filter by value
                                                                <input id="txtSearch" type="text" class="form-control input-sm" ng-model="batchSearch" placeholder="Search" />
                                                                <div class="row">
                                                                    <div class="col-md-offset-6 col-md-6">
                                                                        <div class="row">
                                                                            <div class="col-md-6" style="padding: 5px 0 0 0"><a href="#" style="font-size:12px">Select All</a></div>
                                                                            <div class="col-md-6" style="padding: 5px 15px 0 5px">
                                                                                <a href="#" style="font-size:12px">Clear</a>
                                                                            </div>
                                                                        </div>
                                                                    </div>
                                                                </div>
                                                                <div class="row" style="border-bottom: 1px dotted #ccc!important;">
                                                                    <div class="col-md-12">
                                                                        <div style="height: 150px; overflow-y: scroll; width: 100%;">
                                                                            <ul style="list-style-type: none; padding: 0">
                                                                                <li ng-repeat="emp in employees | unique: 'Country' | filter: batchSearch">
                                                                                    <input id="chkTableList" type="checkbox" ng-model="search[bat.BatchID]" />&nbsp;<label>{{emp.Country}}</label>
                                                                                </li>

                                                                            </ul>
                                                                        </div>
                                                                    </div>
                                                                </div>
                                                                <div class="row" style="margin-top: 8px;">
                                                                    <div class="col-md-12" style="text-align: center">
                                                                        <input id="btnOk" type="button" value="Ok" ng-click="FilterBatchData(BatchID)" class="btn btn-success btn-sm" style="background-color: #0f9d58; border-color: #18804e; color: #fff; padding: 3px; width: 60px;" />
                                                                        <input id="btnCancel" type="button" value="Cancel" class="btn btn-default btn-sm" style="padding: 3px; width: 60px;" />
                                                                    </div>
                                                                </div>
                                                            </form>
                                                        </th>
                                                    </tr>
                                                </table>
                                            </div>
                                        </div>
                                    </div></th>
                                <th>City</th>
                                <th>Name</th>
                            </tr>
                        </thead>
                        <tbody >
                            <tr ng-repeat="emp in employees">
                                 <td>{{emp.City}}</td>
                                 <td>{{emp.Name}}</td>
                                 <td>{{emp.Country}}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</body>

Ответ 1

Мы хотим

  1. Показать список уникальных названий стран с помощью флажков для выбора.
  2. Фильтр списка стран по counrtySearch текстового поля
  3. Отфильтруйте сотрудников с counrtySearch текстового поля counrtySearch и выбранных флажков.

Шаг 1:

Сначала нам нужно создать сопоставление уникальных названий стран. Нам нужен список уникальных названий стран (для итерации) и словарь уникальных названий стран (для легкого доступа без циклов). Следующая функция возвращает оба.

function categorize(arr, field) {
    var o = {}, r = [], i, l = arr.length;
    for (i = 0; i < l; i += 1) {
        if(o[arr[i][field]])continue;
        var _o = {name:arr[i][field], checked:true};
        o[arr[i][field]] = _o;
        r.push(_o);
    }
    return {list:r, dict:o};
};

Шаг 2:

Для фильтрации страны-списка по countrySearch добавить countryFilter и привязка ng-model для флажков.

<li ng-repeat="country in CountryList.list | filter: countryFilter">
    <input id="chk{{$index}}" type="checkbox" ng-model="country.checked" />&nbsp;
    <label for="chk{{$index}}">{{country.name}}</label>
</li>
$scope.countryFilter = function (country) {
    return $scope.countrySearch.length == 0 ? true : country.name.match(new RegExp($scope.countrySearch,'i'));
};

Шаг 3:

Чтобы фильтровать сотрудников по countrySearch и выбранные флажки, добавьте следующий фильтр.

<tr ng-repeat="emp in employees | filter: rowFilter">
    <td>{{emp.Country}}</td>
    <td>{{emp.Name}}</td>
    <td>{{emp.City}}</td>
</tr>
$scope.rowFilter = function (item) {
    return $scope.Countries.dict[item.Country].checked && ($scope.countrySearch.length?item.Country.match(new RegExp($scope.countrySearch,'i')):true);
};

Для пакетного выбора добавьте этот метод в область действия и вызовите markAll(true) чтобы выбрать all, markAll(false) чтобы выбрать none.

$scope.markAll=(b)=>{
    $scope.Countries.list.forEach(function(x){x.checked=b;});
}

Рабочий фрагмент:

var myApp = angular.module('myApp', [])
.controller('employeeController', function ($scope) {
    $scope.countrySearch = "";
    $scope.employees = employees;
    $scope.Countries = categorize(employees, 'Country');
    $scope.countryFilter = function (country) {
        return $scope.countrySearch.length ? country.name.match(new RegExp($scope.countrySearch,'i')):true;
    };
    $scope.rowFilter = function (item) {
        return $scope.Countries.dict[item.Country].checked && ($scope.countrySearch.length?item.Country.match(new RegExp($scope.countrySearch,'i')):true);
    };
    $scope.markAll=(b)=>{
        $scope.Countries.list.forEach(function(x){x.checked=b;});
    }
})

function categorize(arr, field) {
    var o = {}, r = [], i, l = arr.length;
    for (i = 0; i < l; i += 1) {
        if(o[arr[i][field]])continue;
        var _o = {name:arr[i][field], checked:true};
        o[arr[i][field]] = _o;
        r.push(_o);
    }
    return {list:r, dict:o};
};

var employees = [{
    "Name": "Alfreds Futterkiste",
    "City": "Berlin",
    "Country": "Germany"
}, {
    "Name": "Berglunds snabbköp",
    "City": "Luleå",
    "Country": "Sweden"
}, {
    "Name": "Blauer See Delikatessen",
    "City": "Mannheim",
    "Country": "Germany"
}, {
    "Name": "Blondel père et fils",
    "City": "Strasbourg",
    "Country": "France"
}, {
    "Name": "Bólido Comidas preparadas",
    "City": "Madrid",
    "Country": "Spain"
}, {
    "Name": "Bon app'",
    "City": "Marseille",
    "Country": "France"
}, {
    "Name": "Bottom-Dollar Marketse",
    "City": "Tsawassen",
    "Country": "Canada"
}, {
    "Name": "Cactus Comidas para llevar",
    "City": "Buenos Aires",
    "Country": "Argentina"
}, {
    "Name": "Centro comercial Moctezuma",
    "City": "México D.F.",
    "Country": "France"
}, {
    "Name": "Chop-suey Chinese",
    "City": "Bern",
    "Country": "Switzerland"
}, {
    "Name": "Comércio Mineiro",
    "City": "São Paulo",
    "Country": "Canada"
}];
.changeType {
  background: #eee;
  border-radius: 2px;
  border: 1px solid #bbb;
  color: #bbb;
  font-size: 10px;
  line-height: 9px;
  padding: 4px;
  float: right;
}

.changeType:before {
  content: "\25BC ";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script>
  $(document).on('click', '#tblbatch .dropdown-menu', function(e) {
    e.stopPropagation();
  });
</script>

<body ng-app="myApp">
  <div ng-controller="employeeController">
    <div class="container" style="margin-top:40px;">
      <div class="row">
        {{error}}
        <div class="col-md-6">
          <table class="table table-bordered table-condensed">
            <thead>
              <tr>
                <th>Country
                  <div class="dropdown" style="float: right">
                    <button id="btnSearchBatch" class="changeType dropdown-toggle" ng-click="getAllBatchID()" type="button" data-toggle="dropdown"></button>
                    <div class="dropdown-menu prop" aria-labelledby="btnSearchBatch" style="width: 250px; padding: 15px;">
                      <div class="col-md-12" style="padding: 0;">
                        <table style="width:100%">
                          <tr>
                            <th style="text-align: left">
                              <a href="#" class="pull-right" data-dismiss="modal" style="font-size:12px">Close(X)</a>
                              <form class="" role="form">
                                Filter by value
                                <input type="text" class="form-control input-sm" ng-model="countrySearch" placeholder="Search" />
                                <div class="row">
                                  <div class="col-md-offset-6 col-md-6">
                                    <div class="row">
                                      <div class="col-md-6" style="padding: 5px 15px 0 5px"><a href="#" ng-click="markAll(true)" style="font-size:12px">Select All</a> | <a href="#" ng-click="markAll(false)" style="font-size:12px">Select None</a></div>
                                    </div>
                                  </div>
                                </div>
                                <div class="row" style="border-bottom: 1px dotted #ccc!important;">
                                  <div class="col-md-12">
                                    <div style="height: 150px; overflow-y: scroll; width: 100%;">
                                      <ul style="list-style-type: none; padding: 0">
                                        <li ng-repeat="country in Countries.list | filter: countryFilter">
                                          <input id="chk{{$index}}" type="checkbox" ng-model="country.checked" />&nbsp;<label for="chk{{$index}}">{{country.name}}</label>
                                        </li>

                                      </ul>
                                    </div>
                                  </div>
                                </div>
                              </form>
                            </th>
                          </tr>
                        </table>
                      </div>
                    </div>
                  </div>
                </th>
                <th>Name</th>
                <th>City</th>
              </tr>
            </thead>
            <tbody>
              <tr ng-repeat="emp in employees | filter: rowFilter">
                <td>{{emp.Country}}</td>
                <td>{{emp.Name}}</td>
                <td>{{emp.City}}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</body>

Ответ 2

Измените ng-model на одну фиктивную переменную, чтобы сказать emp.status, значение которой будет либо true либо false на основании щелчка.

Выпадающий список HTML-страниц

<li ng-repeat="emp in employees | unique: 'Country' | filter: batchSearch">
   <input id="chkTableList" type="checkbox" ng-model="emp.status" ng-click="yourFunction(emp.status, emp.Country)"/>&nbsp;<label>{{emp.Country}}</label>
                                                                        </li>

Контроллер:

  var countrySet = [];
  $scope.employees=employees;
  $scope.showResults=employees;
  function  _setFilterData(){
      var emplList = angular.copy(employees);

      $scope.showResults = emplList.filter(function(v, idx){
          return countrySet.includes(v.Country)
      });  
  }
  $scope.yourFunction = function(checkBoxStatus, country){
      var index = countrySet.indexOf( country ); 

        if(checkBoxStatus && index === -1 ) {
            countrySet.push( country); 

        }else{
          countrySet.splice( index, 1 );
        }
        _setFilterData();
        console.error(checkBoxStatus, country, countrySet);
    }

Проверьте функциональность плункера: https://plnkr.co/edit/aXhvM0?p=preview

ПРИМЕЧАНИЕ. Никогда не обращайте внимание на CSS на плункер