问题
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