Angular2: HammerJS swipe for md-tab-group

北城以北 提交于 2019-12-11 02:42:45

问题


I've implemented HammerJS in my Angular2 webapp and I've also tested the example code out. This code uses an Array of objects and seems to work flawlessly. However, I've been trying to implement the same system for @angular2-material/tabs. Therefore I have a <md-tab-group> with multiple <md-tab>'s which should swipe from tab to tab. Problem is that I can't even trigger the swipe function.

HTML-File:

<md-tab-group md-stretch-tabs [(selectedIndex)]="selectedIndex" (selectedIndexChange)="selectChange()">
      <div class="swipe-box" (swipeleft)="swipe(idx, $event.type)" (swiperight)="swipe(idx, $event.type)">
        <md-tab>
           (...) //Content Tab 1
        </md-tab>
        <md-tab>
           (...) //Content Tab 2
        </md-tab>
      </div>
</md-tab-group>

In the example can be seen that *ngFor is used like *ngFor="let avatar of avatars; let idx=index" for the swipe-box-<div>. But since I'm getting my index from the <md-tab-group> it doesn't seem neccesary and even when I include it, my event isn't triggered but my <md-tab>-content becomes hidden. Therefore I left it out. I did leave the idx parameter in the function because the swipe method expects a number (second parameter is optional). Documentation

For the TypeScript-file I've implemented the following code (some code might not work but haven't been able to test it since the swipe method doesn't get called).

TS-File:

export class HomeComponent {

  selectedIndex: number = 1;

  selectChange(): void{
    console.log("event triggered INDEX: " + this.selectedIndex);
  }

  SWIPE_ACTION = { LEFT: 'swipeleft', RIGHT: 'swiperight' };

  // Action triggered when user swipes
  swipe(selectedIndex: number, action = this.SWIPE_ACTION.RIGHT) {
    console.log("swiped"); //DOES NOT GET TRIGGERD
    // Out of range
    if (selectedIndex < 0 || selectedIndex > 1 ) return;

    let nextIndex = 0;
    // Swipe right, next tab
    if (action === this.SWIPE_ACTION.RIGHT) {
      const isLast = selectedIndex === 1;
      nextIndex = isLast ? 0 : selectedIndex + 1;
      console.log("swipe right");
    }

    // Swipe left, previous tab
    if (action === this.SWIPE_ACTION.LEFT) {
      const isFirst = selectedIndex === 0;
      nextIndex = isFirst ? 1 : selectedIndex - 1;
      console.log("swipe left");
    }
  }
}

Live demo of what HammerJS does and yes, I've implemented the script needed in the index.html

<!-- Hammer JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.js"></script>

回答1:


I wrote a small directive to accomplish the same effect then your code:

import { Directive, HostListener, EventEmitter, Input, Output } from '@angular/core';

@Directive({
  selector: '[swipeTab]'
})
export class SwipeTabDirective {

  @HostListener('swipeleft', ['$event'])
  onSwipeleft(event) {
    if(this.selectedIndex + 1 <= this.tabs - 1) {
      this.selectedIndex += 1;
      this.selectedIndexChange.emit(this.selectedIndex);
    }
  }

  @HostListener('swiperight', ['$event'])
  onSwiperight(event) {
    if(this.selectedIndex - 1 >= 0) {
      this.selectedIndex -= 1;
      this.selectedIndexChange.emit(this.selectedIndex);
    }
  }

  @Input() tabs: number;
  @Input()  selectedIndex: number;
  @Output() selectedIndexChange = new EventEmitter<number>();

}

The template should look like this:

<md-tab-group md-stretch-tabs [(selectedIndex)]="selectedIndex" [(tabs)]="tabs" swipeTab>
       <md-tab>
          (...) //Content Tab 2
       </md-tab>
       <md-tab>
          (...) //Content Tab 2
       </md-tab>
       <md-tab>
          (...) //Content Tab 3
       </md-tab>           
</md-tab-group>

And in the component you have to declare the following variables:

  selectedIndex: number = 0;
  tabs: number = 3;

Have fun with it.




回答2:


The problem appeared to be that the swipe-event is used in the wrong <div>. The event needs to be triggered in the parent <div>. here's the working code:

HTML-File:

<div class="md-content" flex md-scroll-y (swipeleft)="swipe(idx, $event.type)" (swiperight)="swipe(idx, $event.type)">
   <md-tab-group md-stretch-tabs [(selectedIndex)]="selectedIndex" (selectedIndexChange)="selectChange()">
           <md-tab>
              (...) //Content Tab 1
           </md-tab>
           <md-tab>
              (...) //Content Tab 2
           </md-tab>
   </md-tab-group>
</div

TS-File:

export class HomeComponent {

  selectedIndex: number = 1;

  selectChange(): void{
    console.log("Selected INDEX: " + this.selectedIndex);
  }

  SWIPE_ACTION = { LEFT: 'swipeleft', RIGHT: 'swiperight' };

  // Action triggered when user swipes
  swipe(selectedIndex: number, action = this.SWIPE_ACTION.RIGHT) {
    // Out of range
    if (this.selectedIndex < 0 || this.selectedIndex > 1 ) return;

    // Swipe left, next tab
    if (action === this.SWIPE_ACTION.LEFT) {
      const isLast = this.selectedIndex === 1;
      this.selectedIndex = isLast ? 0 : this.selectedIndex + 1;
      console.log("Swipe right - INDEX: " + this.selectedIndex);
    }

    // Swipe right, previous tab
    if (action === this.SWIPE_ACTION.RIGHT) {
      const isFirst = this.selectedIndex === 0;
      this.selectedIndex = isFirst ? 1 : this.selectedIndex - 1;
      console.log("Swipe left - INDEX: " + this.selectedIndex);
    }
  }
}



回答3:


You need the swipe detection on each tab, not the container.

  <div class="swipe-box">
    <md-tab (swipeleft)="swipe(1, $event.type)" 
            (swiperight)="swipe(1, $event.type)">
       (...) //Content Tab 1
    </md-tab>
    <md-tab (swipeleft)="swipe(2, $event.type)" 
            (swiperight)="swipe(2, $event.type)">
       (...) //Content Tab 2
    </md-tab>
  </div>


来源:https://stackoverflow.com/questions/43118649/angular2-hammerjs-swipe-for-md-tab-group

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!