如何在Angular 8的primeng选项卡视图中为左右导航添加箭头? [英] How to add arrows for left and right navigations in primeng tab view in Angular 8?

查看:110
本文介绍了如何在Angular 8的primeng选项卡视图中为左右导航添加箭头?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望添加左右导航箭头以支持导航中较大的标签页.

我尝试使用primeng,因为我的应用程序已经具有Angular 8这个库.

除了Angular Material之外,还有其他支持此功能的库吗?

我在这里创建了示例.

解决方案

您可以创建自己的指令来实现此目标...

在您的 styles.css 文件中具有以下CSS

  .nav-wrapper {职位:相对溢出:隐藏;填充:0;}.nav-wrapper>ul {显示:flex;}.nav-wrapper--scrollable {填充:0 32px;}.nav-arrow {位置:绝对;显示:无;最高:0;底部:0;z索引:1;边框:1px实心#2399e5;背景:#2399e5;字体:14px/1 FontAwesome;颜色:#fff;光标:指针;}.nav-wrapper--可滚动的.nav-arrow {显示:块;}.nav-arrow:hover {边框:1px实线#1f89ce;背景:#1f89ce;}.nav-arrow:之前{位置:绝对;最高:50%;左:50%;转换:translate(-50%,-50%);}.nav-arrow--左{左:0;}.nav-arrow--left:before {内容:"\ f053";}.nav-arrow--对{正确:0;}.nav-arrow--right:之前{内容:"\ f054";}.nav-arrow-禁用,.nav-arrow--disabled:hover {背景:#ccc;边框:#ddd;游标:默认;} 

创建指令

  import {ContentChildren,指示,ElementRef,输入,NgZone,查询清单}来自"@ angular/core";从"primeng/tabview"导入{TabPanel};从"rxjs"导入{fromEvent,interval,Subject};从"rxjs/operators"导入{delay,mergeMap,take,takeUntil};@指示({选择器:"[appTabScroller]";})导出类TabScrollerDirective {@Input()arrowWidth = 30;@Input()shiftWidth = 25;@ContentChildren(TabPanel)tabPanels:QueryList< TabPanel> ;;私人_container:HTMLElement;private _nav:HTMLElement;私人_shift = 0;private _scrollable:布尔值;private _leftArrow:HTMLElement;private _rightArrow:HTMLElement;私人只读_destroyed $ =新Subject< void>();构造函数(private elRef:ElementRef,私有区:NgZone){}得到rightBorder(){返回-(this._nav.scrollWidth-this._nav.offsetWidth);}ngAfterContentInit(){this.tabPanels.changes.pipe(takeUntil(this._destroyed $)).subscribe(()=> {this.zone.onStable.asObservable().pipe(take(1)).subscribe(()=> this._refreshScroller());});}ngAfterViewInit(){this.zone.runOutsideAngular(()=> this.init());}在里面() {this._nav = this.elRef.nativeElement.querySelector("[role = tablist]");this._container = wrap(this._nav,"nav-wrapper");this._initEvents();this._leftArrow = this._createArrow("left");this._rightArrow = this._createArrow("right");this._refreshScroller();}滚动(移位:数字){this._shift + =移位;const rightBorder = this.rightBorder;如果(this._shift< rightBorder){this._shift = rightBorder;}如果(this._shift> = 0){this._shift = 0;}this._leftArrow.classList.toggle("nav-arrow--disabled",this._shift> = 0);this._rightArrow.classList.toggle(导航箭头已禁用",this._shift< = rightBorder);this._nav.style.transform =`translateX($ {this._shift} px)`;}ngOnDestroy(){this._destroyed $ .next();this._destroyed $ .complete();}私人_initEvents(){fromEvent(this._container,"mousewheel").pipe(takeUntil(this._destroyed $)).subscribe((e:any)=> this._onMouseWheel(e));//FirefoxfromEvent(this._container,"DOMMouseScroll").pipe(takeUntil(this._destroyed $)).subscribe((e:any)=> this._onMouseWheel(e));fromEvent(窗口,调整大小").pipe(takeUntil(this._destroyed $)).subscribe(()=> {this._refreshScroller();});}private _onMouseWheel(e:any){const delta = Math.max(-1,Math.min(1,e.wheelDelta || -e.detail));this.scroll(delta * 25);}私人_createArrow(方向:字符串){const arrow = el(`nav-arrow nav-arrow-$ {direction}`);this._container.insertBefore(箭头,this._nav);arrow.style.width = this.arrowWidth +"px";fromEvent(箭头,点击").pipe(takeUntil(this._destroyed $)).subscribe(()=> {this.scroll(direction ==="left"?this.shiftWidth:-this.shiftWidth);});const upStream $ = fromEvent(arrow,"mouseup");//处理长按fromEvent(箭头,鼠标按下").管道(takeUntil(this._destroyed $),mergeMap(event =>interval(100).pipe(延迟(100),takeUntil(upStream $)))).subscribe(()=> {this.scroll(direction ==="left"?this.shiftWidth:-this.shiftWidth);});返回箭头;}私人_refreshScroller(){const compareWith = this._scrollable吗?-this.arrowWidth * 2:0;this._container.classList.toggle("nav-wrapper--scrollable",this.rightBorder<与之比较);this._scrollable = this.rightBorder<与之比较;this.scroll(0);}}函数wrap(elem,wrapperClass:string){const wrapper = el("nav-wrapper");elem.parentNode.insertBefore(包装器,elem);wrapper.appendChild(elem);返回包装;}函数el(className:string):HTMLElement {const div = document.createElement("div");div.className = className;返回div;} 

现在一切都已设置好,在您的html中

 < p-tabView appTabScroller>< p-tabPanel [header] ="item.content"* ngFor ="让项目中的项目;让我=索引"[选择] ="i == 0".</p-tabPanel></p-tabView> 

请参见演示

来源: https://embed.plnkr.co/BX6UTrG7XTBXS2TNChAs/

I am looking to add left and right navigation arrows to support larger tabs size in nav.

I tried to use primeng as my application already has this library with Angular 8.

Is there any other library that supports this feature other than Angular Material?

I have created my example here.

https://stackblitz.com/edit/primeng-tabview-ngif-hluezs

Angular material example.

https://stackblitz.com/edit/angular-selecting-mattab-bihcd1

解决方案

You can create your own directive to achieve this...

Have the below css in your styles.css file

.nav-wrapper {
  position: relative;
  overflow: hidden;
  padding: 0;
}
.nav-wrapper > ul {
  display: flex;
}

.nav-wrapper--scrollable {
  padding: 0 32px;
}

.nav-arrow {
  position: absolute;
  display: none;
  top: 0;
  bottom: 0;
  z-index: 1;
  border: 1px solid #2399e5;
  background: #2399e5;
  font: 14px/1 FontAwesome;
  color: #fff;
  cursor: pointer;
}
.nav-wrapper--scrollable .nav-arrow {
  display: block;
}
.nav-arrow:hover {
  border: 1px solid #1f89ce;
  background: #1f89ce;
}

.nav-arrow:before {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.nav-arrow--left {
  left: 0;
}
.nav-arrow--left:before {
  content: "\f053";
}

.nav-arrow--right {
  right: 0;
}
.nav-arrow--right:before {
  content: "\f054";
}
.nav-arrow--disabled,
.nav-arrow--disabled:hover {
  background: #ccc;
  border: #ddd;
  cursor: default;
}

Create a directive

import {
  ContentChildren,
  Directive,
  ElementRef,
  Input,
  NgZone,
  QueryList
} from "@angular/core";
import { TabPanel } from "primeng/tabview";
import { fromEvent, interval, Subject } from "rxjs";
import { delay, mergeMap, take, takeUntil } from "rxjs/operators";

@Directive({
  selector: "[appTabScroller]"
})
export class TabScrollerDirective {
  @Input() arrowWidth = 30;
  @Input() shiftWidth = 25;

  @ContentChildren(TabPanel) tabPanels: QueryList<TabPanel>;

  private _container: HTMLElement;
  private _nav: HTMLElement;

  private _shift = 0;
  private _scrollable: boolean;

  private _leftArrow: HTMLElement;
  private _rightArrow: HTMLElement;

  private readonly _destroyed$ = new Subject<void>();

  constructor(private elRef: ElementRef, private zone: NgZone) {}

  get rightBorder() {
    return -(this._nav.scrollWidth - this._nav.offsetWidth);
  }

  ngAfterContentInit() {
    this.tabPanels.changes.pipe(takeUntil(this._destroyed$)).subscribe(() => {
      this.zone.onStable
        .asObservable()
        .pipe(take(1))
        .subscribe(() => this._refreshScroller());
    });
  }

  ngAfterViewInit() {
    this.zone.runOutsideAngular(() => this.init());
  }

  init() {
    this._nav = this.elRef.nativeElement.querySelector("[role=tablist]");
    this._container = wrap(this._nav, "nav-wrapper");

    this._initEvents();

    this._leftArrow = this._createArrow("left");
    this._rightArrow = this._createArrow("right");

    this._refreshScroller();
  }

  scroll(shift: number) {
    this._shift += shift;

    const rightBorder = this.rightBorder;
    if (this._shift < rightBorder) {
      this._shift = rightBorder;
    }
    if (this._shift >= 0) {
      this._shift = 0;
    }

    this._leftArrow.classList.toggle("nav-arrow--disabled", this._shift >= 0);
    this._rightArrow.classList.toggle(
      "nav-arrow--disabled",
      this._shift <= rightBorder
    );

    this._nav.style.transform = `translateX(${this._shift}px)`;
  }

  ngOnDestroy() {
    this._destroyed$.next();
    this._destroyed$.complete();
  }

  private _initEvents() {
    fromEvent(this._container, "mousewheel")
      .pipe(takeUntil(this._destroyed$))
      .subscribe((e: any) => this._onMouseWheel(e));
    // Firefox
    fromEvent(this._container, "DOMMouseScroll")
      .pipe(takeUntil(this._destroyed$))
      .subscribe((e: any) => this._onMouseWheel(e));
    fromEvent(window, "resize")
      .pipe(takeUntil(this._destroyed$))
      .subscribe(() => {
        this._refreshScroller();
      });
  }

  private _onMouseWheel(e: any) {
    const delta = Math.max(-1, Math.min(1, e.wheelDelta || -e.detail));
    this.scroll(delta * 25);
  }

  private _createArrow(direction: string) {
    const arrow = el(`nav-arrow nav-arrow--${direction}`);
    this._container.insertBefore(arrow, this._nav);
    arrow.style.width = this.arrowWidth + "px";
    fromEvent(arrow, "click")
      .pipe(takeUntil(this._destroyed$))
      .subscribe(() => {
        this.scroll(direction === "left" ? this.shiftWidth : -this.shiftWidth);
      });

    const upStream$ = fromEvent(arrow, "mouseup");
    // handle long press
    fromEvent(arrow, "mousedown")
      .pipe(
        takeUntil(this._destroyed$),
        mergeMap(event =>
          interval(100).pipe(
            delay(100),
            takeUntil(upStream$)
          )
        )
      )
      .subscribe(() => {
        this.scroll(direction === "left" ? this.shiftWidth : -this.shiftWidth);
      });

    return arrow;
  }

  private _refreshScroller() {
    const compareWith = this._scrollable ? -this.arrowWidth * 2 : 0;
    this._container.classList.toggle(
      "nav-wrapper--scrollable",
      this.rightBorder < compareWith
    );
    this._scrollable = this.rightBorder < compareWith;
    this.scroll(0);
  }
}

function wrap(elem, wrapperClass: string) {
  const wrapper = el("nav-wrapper");
  elem.parentNode.insertBefore(wrapper, elem);
  wrapper.appendChild(elem);
  return wrapper;
}

function el(className: string): HTMLElement {
  const div = document.createElement("div");
  div.className = className;
  return div;
}

Now everything is set, In your html

<p-tabView appTabScroller>
  <p-tabPanel [header]="item.content" *ngFor="let item of items; let i = index" [selected]="i == 0">
  </p-tabPanel>
</p-tabView>

See Demo

Source: https://embed.plnkr.co/BX6UTrG7XTBXS2TNChAs/

这篇关于如何在Angular 8的primeng选项卡视图中为左右导航添加箭头?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆