Я предлагаю вам использовать position: sticky
( mdn ) в сочетании с first-of-type
для обработки первой строки (в моем собственном проекте я бы стилизовал их, используя классы, но я использую селекторы элементов так,чтобы не менять разметку).
Зная больше о css, вы также можете изменить смещение top
в первом ряду на что-то более адаптивное, но для демонстрации я только что использовалвысота, которая, кажется, работает для меня.Вы также хотите добавить границы.
thead th{
position:sticky;
top:0;
background:white;
}
tbody tr:first-of-type td{
position:sticky;
top:34px;
background:white;
}
var myApp = angular.module('myApp', [])
.controller('employeeController', function($scope) {
$scope.XLfilters = { list: [], dict: {}, results: [] };
$scope.markAll = function(field, b) {
$scope.XLfilters.dict[field].list.forEach((x) => {x.checked=b;});
}
$scope.clearAll = function(field) {
$scope.XLfilters.dict[field].searchText='';
$scope.XLfilters.dict[field].list.forEach((x) => {x.checked=true;});
}
$scope.XLfiltrate = function() {
var i,j,k,selected,blocks,filter,option, data=$scope.XLfilters.all,filters=$scope.XLfilters.list;
$scope.XLfilters.results=[];
for (j=0; j<filters.length; j++) {
filter=filters[j];
filter.regex = filter.searchText.length?new RegExp(filter.searchText, 'i'):false;
for(k=0,selected=0;k<filter.list.length;k++){
if(!filter.list[k].checked)selected++;
filter.list[k].visible=false;
filter.list[k].match=filter.regex?filter.list[k].title.match(filter.regex):true;
}
filter.isActive=filter.searchText.length>0||selected>0;
}
for (i=0; i<data.length; i++){
blocks={allows:[],rejects:[],mismatch:false};
for (j=0; j<filters.length; j++) {
filter=filters[j]; option=filter.dict[data[i][filter.field]];
(option.checked?blocks.allows:blocks.rejects).push(option);
if(filter.regex && !option.match) blocks.mismatch=true;
}
if(blocks.rejects.length==1) blocks.rejects[0].visible=true;
else if(blocks.rejects.length==0&&!blocks.mismatch){
$scope.XLfilters.results.push(data[i]);
blocks.allows.forEach((x)=>{x.visible=true});
}
}
for (j=0; j<filters.length; j++) {
filter=filters[j];filter.options=[];
for(k=0;k<filter.list.length;k++){
if(filter.list[k].visible && filter.list[k].match) filter.options.push(filter.list[k]);
}
}
}
function createXLfilters(arr, fields) {
$scope.XLfilters.all = arr;
for (var j=0; j<fields.length; j++) $scope.XLfilters.list.push($scope.XLfilters.dict[fields[j]]={list:[],dict:{},field:fields[j],searchText:"",active:false,options:[]});
for (var i=0,z; i<arr.length; i++) for (j=0; j<fields.length; j++) {
z=$scope.XLfilters.dict[fields[j]];
z.dict[arr[i][fields[j]]] || z.list.push(z.dict[arr[i][fields[j]]]={title:arr[i][fields[j]],checked:true, visible:false,match:false});
}
}
createXLfilters(employees, ['Country','City']);
})
var employees = [{
"Name": "Manirul Monir",
"City": "Sylhet",
"Country": "Bangladesh"
}, {
"Name": "Arup",
"City": "Sylhet",
"Country": "Bangladesh"
}, {
"Name": "Person 1",
"City": "Dhaka",
"Country": "Bangladesh"
}, {
"Name": "Person 2",
"City": "Dhaka",
"Country": "Bangladesh"
}, {
"Name": "Munim Munna",
"City": "Narshingdi",
"Country": "Bangladesh"
}, {
"Name": "Mahfuz Ahmed",
"City": "Narshingdi",
"Country": "Bangladesh"
}, {
"Name": "Tawkir Ahmed",
"City": "Gazipur",
"Country": "Bangladesh"
}, {
"Name": "Alfreds 2",
"City": "Berlin",
"Country": "Germany"
}, {
"Name": "Alfreds Futterkiste",
"City": "Berlin",
"Country": "Germany"
}, {
"Name": "Blauer See Delikatessen",
"City": "Mannheim",
"Country": "Germany"
}, {
"Name": "Blondel père et fils",
"City": "Strasbourg",
"Country": "France"
}, {
"Name": "Bon app'",
"City": "Marseille",
"Country": "France"
}, {
"Name": "Centro comercial Moctezuma",
"City": "México D.F.",
"Country": "France"
}];
.filterdropdown{
background: #eee;
border: 1px solid #bbb;
color: #bbb;
border-radius: 2px;
font-size: 14px;
line-height: 14px;
}
.filterdropdown.active{
color: #005b9c;
}
a.filterlink{
font-size: 12px;
}
.options {
height: 150px;
overflow-y: scroll;
}
thead th{
position:sticky;
top:0;
background:white;
}
tbody tr:first-of-type td{
position:sticky;
top:34px;
background:white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div class="col-md-6" ng-app="myApp" ng-controller="employeeController">
<table class="table table-bordered table-condensed" data="{{XLfiltrate()}}">
<thead>
<tr>
<th>Country
<div class="dropdown" style="float: right">
<button class="dropdown-toggle filterdropdown" ng-class="{active:XLfilters.dict['Country'].isActive}" type="button" data-toggle="dropdown"><span class="glyphicon glyphicon-filter"></span></button>
<div class="dropdown-menu prop" aria-labelledby="btnSearchBatch" style="width: 250px; padding: 15px;">
<div class="text-right">
<a href="#" class="filterlink" ng-click="clearAll('Country')">Clear All</a> | <a href="#" class="filterlink" data-dismiss="modal">Close(X)</a>
</div>
<form>
<input type="text" class="form-control input-sm" ng-model="XLfilters.dict['Country'].searchText" placeholder="Filter by Country" />
<div>
<a href="#" class="filterlink" ng-click="markAll('Country',true)">Select All</a> | <a href="#" class="filterlink" ng-click="markAll('Country',false)">Select None</a>
</div>
<div class="options">
<ul style="list-style-type: none; padding: 0">
<li ng-repeat="item in XLfilters.dict['Country'].options">
<input id="countryOption{{$index}}" type="checkbox" ng-model="XLfilters.dict['Country'].dict[item.title].checked" /> <label for="countryOption{{$index}}">{{item.title}}</label>
</li>
</ul>
</div>
</form>
</div>
</div>
</th>
<th>City
<div class="dropdown" style="float: right">
<button class="dropdown-toggle filterdropdown" ng-class="{active:XLfilters.dict['City'].isActive}" type="button" data-toggle="dropdown"><span class="glyphicon glyphicon-filter"></span></button>
<div class="dropdown-menu prop" aria-labelledby="btnSearchBatch" style="width: 250px; padding: 15px;">
<div class="text-right">
<a href="#" class="filterlink" ng-click="clearAll('City')">Clear All</a> | <a href="#" class="filterlink" data-dismiss="modal">Close(X)</a>
</div>
<form>
<input type="text" class="form-control input-sm" ng-model="XLfilters.dict['City'].searchText" placeholder="Filter by City" />
<div>
<a href="#" class="filterlink" ng-click="markAll('City',true)">Select All</a> | <a href="#" class="filterlink" ng-click="markAll('City',false)">Select None</a>
</div>
<div class="options">
<ul style="list-style-type: none; padding: 0">
<li ng-repeat="item in XLfilters.dict['City'].options">
<input id="cityOption{{$index}}" type="checkbox" ng-model="XLfilters.dict['City'].dict[item.title].checked" /> <label for="cityOption{{$index}}">{{item.title}}</label>
</li>
</ul>
</div>
</form>
</div>
</div>
</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="emp in XLfilters.results">
<td>{{emp.Country}}</td>
<td>{{emp.City}}</td>
<td>{{emp.Name}}</td>
</tr>
</tbody>
</table>
</div>