【问题标题】:How to add arrows for left and right navigations in primeng tab view in Angular 8?如何在Angular 8的primeng选项卡视图中为左右导航添加箭头?
【发布时间】:2021-06-22 09:52:52
【问题描述】:

我希望添加左右导航箭头以支持导航中更大的标签大小。

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

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

我在这里创建了我的示例。

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

角材料示例。

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

【问题讨论】:

  • 今年 2 月,Prime 添加了以编程方式切换选项卡的功能(版本 11.2.1)primefaces.org/primeng/showcase/#/tabview。只是想检查一下你是否已经看过这个。
  • 我使用的是不支持 Primeng11 的旧版 angular

标签: angular typescript primeng nav


【解决方案1】:

我分叉了您的示例,并在顶部添加了一些示例按钮,这些按钮可以转到上一个/下一个选项卡。当然,有几种不同的方法可以做到这一点。

https://stackblitz.com/edit/primeng-tabview-ngif-2e96sb?file=src/app/app.component.html

让我知道 CSS 是否更重要,因为这主要展示了功能。

【讨论】:

  • 谢谢,如果选项卡大小增加,我的意思是支持箭头,所以不是做下一行,而是与导航箭头在同一行。我用角度材料选项卡中的示例图像更新了问题
  • 啊,那张图说明白了。您是否希望像 Material 一样隐藏大部分选项卡?要完全复制它可能会做太多的工作。您最好将材料引入您的项目并使用它。有很多 UI 框架都有选项卡式视图,但可能没有多少能像 Material 一样做到这一点,如果你喜欢这种方式,为什么不引入 Material 呢?
【解决方案2】:

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

在您的 styles.css 文件中包含以下 css

.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;
}

创建指令

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;
}

现在一切都设置好了,在你的 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

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

【讨论】:

猜你喜欢
  • 2011-12-20
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-20
  • 1970-01-01
相关资源
最近更新 更多