建立具有固定列的可滚动表格

时间:2018-09-18 17:33:02

标签: javascript html css angularjs grid-layout

我需要实现这样的目标

enter image description here

向右滚动是动态的(列数是可变的),而在左侧的第一列是固定的。滚动应该使用图像顶部的箭头,但是我可以协商放弃它。

我的第一个想法是像这样使用flexbox(这是一个模拟示例,我将使用ng-repeat和angular来动态生成结构)

.reporting-table-container {
    display: flex;
    padding-left: 25px;
    padding-right: 10px;
    margin-bottom: 15px;
}

.reporting-table-container .columns-container {
    display: flex;
    overflow-x: scroll;
    margin-right: 15px;
}

.reporting-table-container .columns-container .single-column-container {
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
}

.reporting-table-container .columns-container .single-column-container:nth-child(even), .reporting-table-container .labels-container {
    background-color: #e9e9e9;
}

.reporting-table-container .labels-container {
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
}

.reporting-table-container .labels-container > div {
    width: 100px;
    font-weight: 800px;
}
<div class="reporting-table-container">
    <div class="labels-container">
        <div>ID</div>
        <div>Product Title</div>
        <div>Strategy Name</div>
        <div>Score</div>
        <div>Message</div>
        <div>Feedback</div>
        <div>Clicks</div>
        <div>Conversion Rate</div>
        <div>Revenue</div>
    </div>
    <div class="columns-container">
        <div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
         <div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
         <div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
<div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
<div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
<div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
<div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
<div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
<div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
<div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
<div class="single-column-container">
            <div>2249</div>
            <div>25.5 cu. ft. French Door Refrigerator in Stainless Steel</div>
            <div>Online co-purchase 2wks</div>
            <div>230</div>
            <div>Customer also bough this other item</div>
            <div>43</div>
            <div>0.50%</div>
            <div>$282.830</div>
        </div>
    </div>
</div>

但是很快就发现标签列和数据列之间不会出现边界。此外,我无法(至少没有javascript)匹配同一行的高度(鉴于该行的最大数据,我应该扩展该行的高度)

然后我进入CSS网格布局,但是我不太确定它的外观-与当前示例不同,所有“单元格”都位于同一单元内,因此我不确定如何修复第一列如何设置CSS动态,具体取决于要渲染的项目数。

我该如何实现?

通知:尽管我的代码将使用angularjs动态生成结构,但我相信问题出在纯CSS / HTML上(我想避免使用JavaScript来生成该结构)。

预先感谢

1 个答案:

答案 0 :(得分:0)

我终于设法通过使用CSS网格来解决此问题。

以下是模拟的基本内容,但是我当然会使用真实数据(以及正确加载的图像)。

关键在于使用grid-template-columnsng-style动态分配列数

我仍然缺少图像旁边的自定义滚动条,但我相信这是另外一个故事

(function(){

    function reportingTableController() {
      this.recommendations = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    }

    angular
        .module('app', [])
        .component('reportingTable', {
            template: `<div class="reporting-table-container" ng-style="{'grid-template-columns': '90px repeat({{$ctrl.recommendations.length + 1}}, 130px)'}">
    <div style="grid-row:1;" class="row-label-title"></div>
    <div style="grid-row:2;" class="row-label-title">ID</div>
    <div style="grid-row:3;" class="row-label-title">Product Title</div>
    <div style="grid-row:4;" ng-style="{'grid-column-end': $ctrl.recommendations.length + 2}" class="orange-delimiter"></div>
    <div style="grid-row:5;" class="row-label-title">Strategy Name</div>
    <div style="grid-row:6;" class="row-label-title">Score</div>
    <div style="grid-row:7;" class="row-label-title">Message</div>
    <div style="grid-row:8" ng-style="{'grid-column-end': $ctrl.recommendations.length + 2}" class="orange-delimiter">></div>
    <div style="grid-row:9;" class="row-label-title">Feedback</div>
    <div style="grid-row:10;" class="row-label-title">Clicks</div>
    <div style="grid-row:11;" class="row-label-title">Conversion Rate</div>
    <div style="grid-row:12;" class="row-label-title">Revenue</div>

    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 1, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        <img src="Angular/app/RecommendationsTab/mock.png" alt="recommendation image" />
    </div>

    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 2, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        2249
    </div>
    
    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 3, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        25.5 cu. ft. French Door Refrigerator in Stainless Steel
    </div>
    
    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 5, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        Online co-purchase 2wks
    </div>
    
    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 6, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        230
    </div>
    
    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 7, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        Customer also bough this other item
    </div>
    
    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 9, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        Mailbox
    </div>
    
    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 10, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        43
    </div>
    
    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 11, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        0.50%
    </div>
    
    <div ng-class-even="'even-cell'" class="reporting-table-cell" ng-style="{'grid-row': 12, 'grid-column': $index + 2 }" ng-repeat="recommendation in $ctrl.recommendations">
        $282.830
    </div>
</div>`,
            controller: reportingTableController,
        });
})();
.reporting-table-container {
    display:grid;
    padding-right: 10px;
    margin-bottom: 15px;
    margin-left: 25px;
    background-color: white;
    overflow-x: scroll;
}

.reporting-table-container .row-label-title {
    font-weight: 800;
    left: 0;
    position: sticky;
    grid-column: 1;
}

/* grid cells*/
.reporting-table-container > div {
    padding-left: 6px;
    padding-right: 6px;
    padding-top: 8px;
    padding-bottom: 10px;
}

.reporting-table-container .row-label-title, 
.reporting-table-container .reporting-table-cell.even-cell {
    background-color: #e9e9e9;
}

.reporting-table-container .reporting-table-cell, 
.reporting-table-container .row-label-title {
    border-bottom: #d1d1d1 1px solid;
}

.reporting-table-container .row-label-title:first-of-type {
    background-color: white;
    border-bottom: none;
}

.reporting-table-container .orange-delimiter {
    border: 1px solid #f96302;
    background-color: white;
    grid-column-start: 1;
    height: 1px;
    margin-bottom: 3px;
    margin-top: 3px;
    padding: 0;
}

.reporting-table-container .reporting-table-cell > img {
    max-width: calc(100% - 12px);/* 12 px of padding*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js"></script>
<body>
  <div ng-app="app">
   <reporting-table></reporting-table>
  </div>
</body>