PrimeNG Table Sticky 的用法

  • 先牢骚,官方给的代码用在 Angular8 RxJS6 版本上有兼容的问题,主要是 RxJS6 有很多 breaking changes ,下面贴出来自己验证过成功的代码 - 2019年7月30日 13:15:31

  • 制作指令:

    
    import { Directive, Input, Renderer, ElementRef, AfterViewInit, OnDestroy, OnChanges } from '@angular/core';
    import { Subscription,fromEvent } from 'rxjs';
    @Directive({
        selector: '[stickyHeader]'
    export class StickyHeaderDirective implements AfterViewInit, OnDestroy, OnChanges{
        private windowScrollSubscription: Subscription = null;
        private windowResizeSubscription: Subscription = null;
        private header: any = null;
        private offsetTop: number = 0;
        private lastScroll: number = 0;
        private isSticky: boolean = false;
        private hasHeader: boolean = false;
        private headerTop = 0;
        @Input('stickyClass') stickyClass: string = "";
        @Input('stickyTop') stickyTop: number = 0;
        constructor(private elementRef: ElementRef, private renderer: Renderer) {
        ngAfterViewInit(): void {
            setTimeout(()=>{
                this.windowScrollSubscription = fromEvent(window, 'scroll').subscribe(() => this.manageScrollEvent());
                this.windowResizeSubscription = fromEvent(window, 'resize').subscribe(() => this.updateHeaderSize());
                const headers = this.elementRef.nativeElement.getElementsByTagName('TR');
                this.hasHeader = headers.length > 0;
                if (this.hasHeader) {
                    this.header = headers[0];
                    this.headerTop = this.header.getBoundingClientRect()['top'];
                    this._calcPosition();
            }, 0);
        ngOnDestroy(): void {
            if (this.windowScrollSubscription){
                this.windowScrollSubscription.unsubscribe();
                this.windowScrollSubscription = null;
            if (this.windowResizeSubscription){
                this.windowResizeSubscription.unsubscribe();
                this.windowResizeSubscription = null;
        ngOnChanges(changes)
            if (changes.stickyTop) {
                this._calcPosition();
        private _calcPosition(){
            if (this.hasHeader) {
                const scroll = window.pageYOffset;
                if (this.isSticky && scroll >= this.headerTop) {
                    this.header.style.top =  this.stickyTop + 'px';
        private manageScrollEvent(): void {
            const scroll = window.pageYOffset;
            if (scroll > this.lastScroll && !this.isSticky && scroll >= this.offsetTop) {
                this.setSticky();
            } else if (scroll < this.lastScroll && this.isSticky && scroll <= this.offsetTop) {
                this.unsetSticky();
            this.lastScroll = scroll;
        private setSticky(): void {
            this.isSticky = true;
            this.header.style.position = 'fixed';
            this.header.style.top =  this.stickyTop + 'px';
            this.header.style.display = 'table';
            this.updateHeaderSize();
            this.setClass(true);
        private updateHeaderSize(){
            if (this.isSticky) {
                const tableWidth = this.elementRef.nativeElement.getBoundingClientRect()['right'] - this.elementRef.nativeElement.getBoundingClientRect()['left'];
                this.header.style.width = tableWidth + 'px';
                // update size of TH elements
                const thArray = this.elementRef.nativeElement.getElementsByTagName('TH');
                for (let i = 0; i < thArray.length; i++){
                    thArray[i].style.width = tableWidth / thArray.length + "px";
        private unsetSticky(): void {
            this.isSticky = false;
            this.header.style.position = 'static';
            this.header.style.width = 'auto';
            this.header.style.display = 'table-row';
            this.setClass(false);
        private setStyle(key: string, value: string): void {
            this.renderer.setElementStyle(this.header, key, value);
        private setClass(add: boolean): void {
            if (this.stickyClass){
                this.renderer.setElementClass(this.header, this.stickyClass, add);
      
    • 将制作的指令导入组件所在模块
      在这里插入图片描述- 模板中使用 sticky 指令:
      在这里插入图片描述上面被注释的属性 [stickyTop]=50 可以指定下拉时列头举例屏幕上面的举例
  • 设置 css 样式:

    .header{
        height: 50px;
        width: 100%;
        background-color:cornflowerblue;
        color: white;
        font-size: 16px;
        font-weight: bold;
        font-family: Arial;
        line-height: 50px;
        text-align: center;
        border-bottom: 1px solid #666666;
        position: fixed;
        z-index: 1;
        top: 0px;
    p-dataTable{
        margin-left: 20px;
        margin-top: 50px;
        margin-right: 20px;
        display: block;
    :host /deep/ p-datatable .stickyHeader{
      box-shadow: 2px 2px 1px #888888;
      
    • 最终效果
      在这里插入图片描述- 纠正官方代码的不兼容问题:
      在这里插入图片描述
PrimeNG Table Sticky 的用法先牢骚,官方给的代码用在 Angular8 和 RxJS6 版本上有兼容的问题,主要是 RxJS6 有很多 breaking changes,下面贴出来自己验证过成功的代码 - 2019年7月30日 13:15:31...
在组件的 angular 项目用npm安装 primeng 的官方包: 详细做法参见官方网址:https://www.primefaces.org/ primeng /showcase/#/setup 在使用到p- table 控件的module中导入 import { Table Module} from ' primeng / table '; @NgModule({ imports: [ Table ...
**问题:**我们发现,只要设置了border边框,这个位置滑动有内容经过就会出现如图的情况。 **解决的方法:**用outline(轮廓)替代border,以达到我们想要的样式。 table thead tr { border: none; outline-color: #fff; outline-style: solid; outline-width: 1px; outline主要是在元素边框的外围设置轮廓,outline不占据空间,绘制于元素内容周围。同时.
问题描述:系统有两个导航栏,一个是kendo的menu,另外一个kendo的mobilegroupbutton. 系统已经添加了ui-router-extras相关的js, angular 也设置了 sticky :true。 mobilegroupbutton是根据kedo menu的选项来生成的,现在groupbutton里面查找有无当前选项的对象值, 若没有就添加到groupbutton...
个人觉得 primeng 提供了很多比较好看的组件,包括输入框input、表格 table 、按钮button、交互框dialog等等,样式要比 angular material好看一些,也比较好上手,官网提供了很多示例代码以及参数的使用说明。 但是某些组件的元素样式说明可能没有很直接,所以想开这篇文章,介绍一下我在使用其中一些组件时遇到的问题,以及对应的解决方案,包括一些内部元素的css设置。 1. 单选多选表格, &lt;p- table &gt; 不可添加 dataKey="vin",否则选中样式为所有行; 2. 表格宽度随内容适应,&lt;p- table &gt; 添加 autoLayout="true"; 3. 后台得到的数据需要映射,通过自定义管道实现,遍历数据找到该项;...
PrimeNG p- Table 自定义shift多选功能1) 需求:2) 思路:3) 代码实现: 1) 需求: 项目需求在数据列表中实现:按住shift上下实现多选、单独上下键实现选中行上下移动。 2) 思路: 利用keydown事件实现,html代码: &amp;amp;lt;p- table (keydown)=&amp;quot;OnKeyDownHandler($event)&amp;quot;&amp;amp;gt;&amp;amp;lt;p-tab
3. 在 Angular 的项目根目录下的 ` angular .json` 文件中,找到 `projects.<your-project-name>.architect.build.options.styles` 属性,并将其修改为以下内容: "styles": [ "input": "src/styles.css", "postcss": true 4. 在你的 CSS 文件中,使用 PostCSS 提供的功能。例如,你可以使用 Autoprefixer 插件自动添加浏览器前缀: ```css .my-element { display: flex; 在编译后,这会被转换为: ```css .my-element { display: -webkit-box; display: -ms-flexbox; display: flex; 希望这对你有帮助!