I try to override the phone's back button in my Ionic App.
This code permit me to open a modal to close the App if I'm not in a page, else close the page.
But this doesn't allow me to close an opened modal. How can I detect if I'm in a modal to close it ?
platform.registerBackButtonAction(() => {
let nav = app.getActiveNav();
let activeView: ViewController = nav.getActive();
console.log(activeView);
if(activeView != null){
if(nav.canGoBack()) {
activeView.dismiss();
} else{
let alert = this.alertCtrl.create({
title: this.pdataManager.translate.get("close-app"),
message: this.pdataManager.translate.get("sure-want-leave"),
buttons: [
{
text: this.pdataManager.translate.get("no"),
handler: () => {
this.presentedAlert = false;
},
role: 'cancel',
},
{
text: this.pdataManager.translate.get("yes"),
handler: () => {
this.presentedAlert = false;
this.platform.exitApp();
}
}
]
});
if(!this.presentedAlert) {
alert.present();
this.presentedAlert = true;
}
}
}
});
}
1.Import IonicApp:
import {IonicApp } from 'ionic-angular';
2.Add to your constructor:
private ionicApp: IonicApp
3.Inside your platform.registerBackButtonAction add:
let activeModal=this.ionicApp._modalPortal.getActive();
if(activeModal){
activePortal.dismiss();
return;
}
I found the answer here :
https://github.com/ionic-team/ionic/issues/6982
You can give page name to your modal and you can access it from anywhere in app. Try this..
import { App } from 'ionic-angular';
constructor(public app: App){
}
platform.registerBackButtonAction(() => {
let nav = this.app.getActiveNav();
let view = nav.getActive().instance.pageName;
if (view == YOU_PAGE_NAME) {
//You are in modal
} else {
//You are not in modal
}
});
Inside your modal
pageName = 'YOU_PAGE_NAME';
In the end I have this for my back button:
constructor(private platform: Platform, private config: ConfigService, private nfc: NfcService, private alertCtrl: AlertController,
public events: Events, private translate: TranslateService, private fetch: ConfigFetchService, private menuList: MenuList, private ionicApp: IonicApp,
private menuCtrl: MenuController
) {
platform.ready().then(() => {
this.config.pullVersion();
let ready = true;
platform.registerBackButtonAction(() => {
Logger.log("Back button action called");
let activePortal = ionicApp._loadingPortal.getActive() ||
ionicApp._modalPortal.getActive() ||
ionicApp._toastPortal.getActive() ||
ionicApp._overlayPortal.getActive();
if (activePortal) {
ready = false;
activePortal.dismiss();
activePortal.onDidDismiss(() => { ready = true; });
Logger.log("handled with portal");
return;
}
if (menuCtrl.isOpen()) {
menuCtrl.close();
Logger.log("closing menu");
return;
}
let view = this.nav.getActive();
let page = view ? this.nav.getActive().instance : null;
if (page && page.isRootPage) {
Logger.log("Handling back button on a home page");
this.alertCtrl.create({
title: translate.instant('Confirmation'),
message: translate.instant('Do you want to exit?'),
buttons: [
{
text: translate.instant('Cancel'),
handler: () => {
}
},
{
text: translate.instant('OK'),
handler: () => {
platform.exitApp();
}
}
]
}).present();
}
else if (this.nav.canGoBack() || view && view.isOverlay
) {
Logger.log("popping back");
this.nav.pop();
}
else if (localStorage.getItem('is_logged_in')
) {
Logger.log("Returning to home page");
this.nav.setRoot(HomePage);
}
else if (!localStorage.getItem('is_logged_in')) {
Logger.log("Not yet logged in... exiting");
platform.exitApp();
}
else {
Logger.log("ERROR with back button handling");
}
}, 1);
....
Related
I have these two grid. The bottom one is based on the top one:
Each of the items in the lower grid is related to the Program Name and the Tool# selected from the top grid. In this picture the "Delete Tool Change" button is enable since I have selected an item from the lower grid.
Now, if I choose a different Program name and Tool# (Eg: from #6 to 1 on the top grid), and choose a different item from the bottom grid(Eg:1#), it suddenly disables the "Delete Tool Change" button.
The two grid after choosing a different item from upper grid
This is my code for the upper grid component.
columns: ColumnDef[] = [
{ field: 'programName', name: 'Program Name', editable: false, filterField: true, width: '12em', tooltip: 'Read Only' },
{ field: 'toolNoPrefix', name: 'Tool #(Prefix)', editable: false, filterField: true, width: '12em', tooltip: 'First 8 characters of the Tool Tip - Read Only' },
{ field: 'toolNoSuffix', name: '(Suffix)', filterField: true, width: '8em' },
{ field: 'toolName', name: 'Tool Name', editable: false, filterField: true, width: '24em' },
{ field: 'tlLeadFileName', name: 'Tool File Name' },
{ field: 'typeName', name: 'Fixture Type', editable: false, width: '12em' },
{field: 'engineerId', name: 'MSE', type: 'dropdown',
optionsList: this.engineers, optionsListField: 'id', optionsListName: 'lastFirstName', width: '10em'},
{ field: 'userSource', name: 'User Source', editable: false, width: '12em' },
{ field: 'tprCreateDate', name: 'Date Created', type: 'date', editable: false, width: '8em' },
];
hasLoaded = false;
resourced = false;
selectedEcmTool$: BehaviorSubject<any> = new BehaviorSubject(null);
#ViewChild('tools') dataTable: DataTableComponent;
constructor(
private router: Router,
private cgpAlertDialogService: CgpAlertDialogService,
private ecmService: EcmService,
private dialog: MatDialog,
private readonly toastr: ToastrService
) {}
ngOnInit() {
if (!this.selectionCriteria) {
this._init = this.cgpAlertDialogService.showAlertDialog({
title: 'Invalid Selection Criteria',
message: 'A selection criteria has not been selected. Redirecting back to the main page.',
alert: cgpAlertTypes.warning,
closeLabel: 'OK'
}).afterClosed().subscribe(
() => this.router.navigate([''])
);
}
if (this.router.url === '/tprecm/ecm/re-source') {
this.resourced = true;
this.columns.forEach(val => val.editable = false);
}
this.updateNameSources();
this.hasLoaded = true;
}
ngOnDestroy() {
if (this._init) {
this._init.unsubscribe();
}
}
loadECMs() {
this.loading = true;
const body = {
...this.selectionCriteria,
filterColumn: this._currentFilters,
reSourced: +this.resourced,
};
this.ecmService.getAllTools(body, this.pageOptions)
.pipe(
filter(Boolean),
finalize(() => this.loading = false)
).subscribe((res: { totalCount: number, data: any[] }) => {
this.total = res.totalCount;
this.data = res.data;
if (this.data.length >= 1) {
this.dataTable.selections = [this.data[0]];
this.selectedEcmTool$.next(this.data[0]);
}
});
}
onSelect(selectedEcmTool) {
this.selectedEcmTool$.next(selectedEcmTool);
}
This is my html for the uppergrid:
<cgp-app-card titleText="View/Update ECM" showFullScreenToggle="true" [showBackButton]="true"
[onBackButtonClicked]="onBackButtonClicked">
<div *ngIf="hasLoaded">
<data-table #tools [data]="data" [columns]="columns" (lazyLoad)="onLazyLoad($event)" [lazy]="true" [paging]="true"
[pageSize]="pageOptions.size" [totalRecords]="total" [loading]="loading" [filterable]="true" (edit)="updateTool($event)"
(select)="onSelect($event)">
<ng-container actionStart>
<button mat-button (keypress)="onEcmNecReportsClick()" (click)="onEcmNecReportsClick()">Nec Reports</button>
<button mat-button (keypress)="onEcmReportsClick()" (click)="onEcmReportsClick()">ECM Reports</button>
<button mat-button (keypress)="onToolPartRelationshipClick()" (click)="onToolPartRelationshipClick()">Edit
Tool/Part Relationship</button>
<button mat-button (keypress)="onEcmPartsClick()" (click)="onEcmPartsClick()">Parts</button>
<button mat-button [disabled]="this.resourced" (keypress)="onEcmPartsUploadClick()"
(click)="onEcmPartsUploadClick()">Upload Parts from a File</button>
</ng-container>
<ng-container actionEnd>
<button mat-button>Change Log</button>
</ng-container>
</data-table>
<ecm-tool-change [resourced]="this.resourced" [selectedEcmTool$]="selectedEcmTool$"></ecm-tool-change>
</div>
</cgp-app-card>
This is my code for the lower grid component:
#Input() selectedEcmTool$: BehaviorSubject<any>;
#ViewChild('toolChangeTable') toolChangeTable: DataTableComponent;
constructor(
private readonly ecmToolChangeService: EcmToolChangeService,
private readonly ecmService: EcmService,
private readonly dialog: MatDialog,
private readonly toastr: ToastrService,
private readonly confirmation: CgpConfirmationDialogService,
private readonly cgpAlertDialogService: CgpAlertDialogService,
) {
}
onSelect(selectedEcmTool, toolChangeTable: DataTableComponent) {
if (selectedEcmTool.dtShippedToDatabank) {
const selected = toolChangeTable.selections;
const index = selected.findIndex(s => s.toolId === selectedEcmTool.toolId);
if (index !== -1) {
toolChangeTable.selections.splice(index, 1);
}
this.toastr.error('You cannot check this Tool Change after you have entered the Shipped to Databank Date ');
}
}
onUnSelect(dataItem) {
return dataItem;
}
ngOnInit() {
if (this.resourced) {
this.columns.forEach((val) => val.editable = false);
}
this.selectedEcmTool$.subscribe(
(selectedEcmTool) => {
if (selectedEcmTool) {
const toolId = selectedEcmTool.toolId;
this.updateSelectedEcmTool(toolId);
this.updateDesignSources();
} else {
this.data = [];
}
}
);
}
ngOnDestroy() {
if (this.selectedEcmTool$) { this.selectedEcmTool$.unsubscribe(); }
}
onLazyLoad(event: LazyLoadEvent) {
this.pageOptions.order = event.sortOrder === 1 ? 'asc' : 'desc';
this.pageOptions.size = event.rows;
this.pageOptions.sort = event.sortField;
this.pageOptions.page = event.first / this.pageOptions.size;
this.updateSelectedEcmTool(this.toolId);
}
clearSelections() {
this.toolChangeTable.selections = [];
}
updateSelectedEcmTool(toolId) {
if (!toolId) {
return;
}
this.toolId = toolId;
this.loading = true;
this.ecmToolChangeService.getToolChange(toolId, this.pageOptions)
.pipe(filter(Boolean))
.subscribe({
next: (res: { totalCount: number, data: any[] }) => {
this.total = res ? res.totalCount : 0;
this.data = res ? res.data : [];
},
complete: () => this.loading = false
});
}
updateToolChange(event: any) {
const body = event.data;
body.sourceName = undefined;
this.ecmToolChangeService.updateToolChange(body)
.subscribe();
}
This is my code for the lower grid html:
<data-table #toolChangeTable [columns]="columns" [data]="data" [loading]="loading" (lazyLoad)="onLazyLoad($event)" [lazy]="true"
[lazyLoadOnInit]="false" [pageSize]="pageOptions.size" [multiselect]="true" [paging] = "true" [totalRecords]="total"
defaultSortField="necLec" (edit)="updateToolChange($event, toolChangeTable)" (select)="onSelect($event, toolChangeTable)" (unSelect)="onUnSelect($event)">
<ng-container actionStart>
<button mat-button (click)="onMultiRowUpdateClick()" (keypress.enter)="onMultiRowUpdateClick()"
[disabled]="this.resourced || hasSelectedNone">Multi-Edit</button>
<button mat-button (click)="clearSelections()" (keypress.enter)="clearSelections()">Clear All</button>
<button mat-button (click)="onAddToolChangeClick()" [disabled]="this.resourced">Add Tool Change</button>
<button mat-button (click)="onDeleteToolChangeClick()" (keypress.enter)="onDeleteToolChangeClick()"
[disabled]="!hasSelectedSingle">Delete Tool Change</button>
<button mat-button [disabled]="!hasSelectedSingle" (click)="onEditAuthoritiesClick()"
(keypress.enter)="onEditAuthoritiesClick()">Edit Tool Change
Authorities</button>
</ng-container>
</data-table>
How can I write a function or trigger ngOnDestroy so that it does not remembers the previously selected rows anymore.
why not just call clearSelections() from within this.selectedEcmTool$.subscribe()?
every time the selectedEcmTool$ observable gets a new value, the lower grid clears it's selections.
or am I missing something?
ngOnInit() {
if (this.resourced) {
this.columns.forEach((val) => val.editable = false);
}
this.selectedEcmTool$.subscribe(
//clear selections whenever the tool changes
this.clearSelections();
(selectedEcmTool) => {
if (selectedEcmTool) {
const toolId = selectedEcmTool.toolId;
this.updateSelectedEcmTool(toolId);
this.updateDesignSources();
} else {
this.data = [];
}
}
);
}
I fixed it by adding:
get hasSelectedSingleCheck(): boolean {
return (this.toolChangeTable.selections || [])
.filter((row) => row.toolId === this.selectedToolId).length === 1;
}
and adding this check in the html to disable the button if its true.
I have an angular7 app in which i am using ngx-dialogs. I am using this modal for confirmation modal for delete purpose. I open modal to prompt user that "you want to sure to delete", if user click on "Yes" so item is deleted and modal should be close. I have this implementation in my component.ts
import { Ngxalert } from 'ngx-dialogs';
// after class intialization
confirmAlert: any = new Ngxalert;
delete = (rowData: Users) => {
if (rowData) {
this.confirmAlert.create({
title: 'Delete Warning',
message: 'Are you sure, you want to delete item?',
confirm: () => {
this._dataService.delete(this._constant.user + '/' + rowData._id)
.subscribe(res => {
console.log('delete response : ',res);
console.log('html element',(<HTMLElement>document.querySelector('.ngx-dialog')));
(<HTMLElement>document.querySelector('.ngx-dialog')).style.display = "none";
this._utilityService.hideSpinner();
if (res) {
res.success ? this._utilityService.showToster(res.message, 'Notification', 'success') : this._utilityService.showToster(res.message, 'Notification', 'danger');
// this.getUsers();
}else{
(<HTMLElement>document.querySelector('.ngx-dialog')).style.display = "none";
}
this.getUsers();
this._utilityService.hideSpinner();
}, error => {
this._utilityService.hideSpinner();
(<HTMLElement>document.querySelector('.ngx-dialog')).style.display = "none";
console.log('User Delete Error : ', error);
// this._popupService.OpenError('Having some issue..!');
this._utilityService.showToster('Having Some Issue..!', 'Warning', 'warning');
this.getUsers();
})
},
})
}
}
In this delete function when i received response from sever so i close that modal using this
(<HTMLElement>document.querySelector('#ngxdialog-1')).style.display = "none";
And it modal is closing only if i open inspect element or if i resize my chrome to smaller screen. But it's not closing modal on desktop screen. I don't know why is it happening. If it is closing modal on smaller screen so it should also close modal on desktop screen. It closes the modal if i delete item when inspect element. Please refer this video here
The issue is the code inside .subscribe() does not trigger an update in the html. A fix is using the ngZone provider.
You can try running your code inside Angular NgZone :
import { Ngxalert } from 'ngx-dialogs';
import { NgZone } from '#angular/core';
constructor(private ngZone: NgZone) { }
// after class intialization
confirmAlert: any = new Ngxalert;
delete = (rowData: Users) => {
if (rowData) {
this.confirmAlert.create({
title: 'Delete Warning',
message: 'Are you sure, you want to delete item?',
confirm: () => {
this._dataService.delete(this._constant.user + '/' + rowData._id)
.subscribe(res => {
this.ngZone.run(() => {
console.log('delete response : ',res);
console.log('html element',(<HTMLElement>document.querySelector('.ngx-dialog')));
(<HTMLElement>document.querySelector('.ngx-dialog')).style.display = "none";
this._utilityService.hideSpinner();
if (res) {
res.success ? this._utilityService.showToster(res.message, 'Notification', 'success') : this._utilityService.showToster(res.message, 'Notification', 'danger');
// this.getUsers();
}else{
(<HTMLElement>document.querySelector('.ngx-dialog')).style.display = "none";
}
this.getUsers();
this._utilityService.hideSpinner();
});
}, error => {
this._utilityService.hideSpinner();
(<HTMLElement>document.querySelector('.ngx-dialog')).style.display = "none";
console.log('User Delete Error : ', error);
// this._popupService.OpenError('Having some issue..!');
this._utilityService.showToster('Having Some Issue..!', 'Warning', 'warning');
this.getUsers();
})
},
})
}
}
You can find the issue here: https://github.com/angular/angular/issues/31749
It sounds like the modal is only closing on resize because resize is when the browser has to re-render, which applies the styles such as display:none. I'm not super familiar with Angular 7 but I think the answer is to trigger a render. Can you get rid of the tag to manipulate the DOM directly? That tag may refer to a virtual DOM.
I'm studying javascript and mithril.js 1.1.6. I'm writing down a simple web app in which users land on a page where he can login. Users who already did login land on a different page. I'm trying this using conditional routing, here is the main component:
const m = require("mithril");
...
import Eventbus from './whafodi/eventbus.js';
import WelcomePage from './ui/welcome.js';
import User from './model/user.js';
var eventbus = new Eventbus();
function MyApp() {
return {
usrAuth: function() {
m.route(document.body, "/", {
"/": { view: () => m("p", "hello")}
})
},
usrNotAuth: function() {
m.route(document.body, "/", {
"/": { render: v => m(WelcomePage, eventbus) }
})
},
oninit: function(vnode) {
vnode.state.user = new User();
eventbus.subscribe({
type: "login",
handle: function(action) {
vnode.state.user.token = action.token;
console.log(JSON.stringify(vnode.state.user));
}
});
},
view: function(vnode) {
if(vnode.state.user.token) {
this.usrAuth();
} else {
this.usrNotAuth();
}
}
}
};
m.mount(document.body, MyApp);
MyApp is the main component. It check if user has a token, then return the proper route. This is the component that is in charge to let users login:
const m = require("mithril");
const hellojs = require("hellojs");
function TopBar(node) {
var bus = node.attrs.eventbus;
function _login() {
hellojs('facebook').login({scope:'email'});
}
return {
oninit: function(vnode) {
hellojs.init({
facebook: XXXXXXX,
}, {
redirect_uri: 'http://localhost'
});
hellojs.on('auth.login', auth => {
var fbtoken = auth.authResponse.access_token;
m.request({
method:"POST",
url:"./myapp/login/fb/token",
data:auth.authResponse,
background: true
}).then(function(result){
console.log(result);
bus.publish({ type: "login", token: result.jwttoken });
m.route.set("/");
}, function(error){
console.log(error);
bus.publish({ type: "login", token: "" });
});
});
},
view: function(vnode) {
return m("div", [
m("button", { onclick: _login }, "Login")
]);
}
}
}
export default TopBar;
TopBar component occurs in the WelcomePage component mentioned in the main one. TopBar renders a button and use hello.js to login. It uses the EventBus bus parameter to tell main component user logged in (there is an handler in main component to update the user model). Once user logins, event is fired and main component updates the user model. Good. Now, how can trigger the main component to load the right route?
I read mithril'docs again and I found that RouteResolvers perfectly suit my needs. Here is an example:
var App = (function() {
var login;
function isLoggedIn(component) {
if(login) {
return component;
} else {
m.route.set("/hey");
}
}
return {
oninit: function(vnode) {
EventBus.subscribe({
type: "login",
handle: function(action) {
console.log("incoming action: " + JSON.stringify(action));
login = action.value;
}
});
},
oncreate: function(vnode) {
Foo.eventbus = EventBus;
Bar.eventbus = EventBus;
Hey.eventbus = EventBus;
m.route(document.body, "/hey", {
"/foo": {
onmatch: function(args, requestedPath, route) { return isLoggedIn(Foo); }
},
"/bar": {
onmatch: function(args, requestedPath, route) { return isLoggedIn(Bar); }
},
"/hey": Hey
});
},
view: function(vnode) {
return m("div", "home..");
}
};
})();
Eventbus is used to let components communicate with App. They fire events (login type events) that App can handle. I found convenient to pass Eventbus the way oncreate method shows, I can use Eventbus in each component's oncreate to let components fire events.
Hi so in the app I am working on, I have this constructor that checks the redux store for error messages being passed by various components. It displays the error or success messages just fine. However once the user dismisses the banner (by clicking x) and I go to another person's portfolio the banner no longer shows error or success messages
constructor(private store: Store<State>) {
store
.select(StatusBannerState)
.map(data => {
return data.status_banner;
})
.subscribe(banner_state => {
if (banner_state.success_list.length > 0) {
this.showBanner = true;
this.bannerMessage = this.createSuccessBannerMessage(
banner_state.success_list
);
setTimeout(() => {
this.store.dispatch(new BannerDimissesSuccessMessage());
this.bannerMessage = this.createErrorBannerMessage(
banner_state.error_list
);
}, 5000);
} else if (banner_state.error_list.length > 0) {
this.bannerMessage = this.createErrorBannerMessage(
banner_state.error_list
);
} else {
this.showBanner = false;
this.bannerMessage = '';
}
});
}
I have this test function at the moment which I call in the createErrorMessage function to show or hide the funciton (I call it in the HTML component of the angular app)
showOrHideBanner(errorWidget) {
errorWidget.length === 0
? (this.showBanner = false)
: (this.showBanner = true);
}
I have another method that clears the redux store on initialization
ngOnInit() {
this.store.dispatch(new UserDismissesEverything());
}
What would be the best way to check for error messages again after the user has dismissed the banner
update: code for close
onCloseClick() {
this.close.emit(true);
this.show = false;
this.clearTimeout(this.timeoutId);
}
HTML component code
<div class="mt-1 container">
<div class="alert-box">
<div *ngIf="bannerMessage" class="px-3 mb-1">
<glass-alert-box
(close)="hideTheBanner()"
[success]="bannerMessageType == 'success'">{{ bannerMessage}}
</glass-alert-box>
</div>
</div>
</div>
Try following code:
constructor(private store: Store<State>) {
}
ngOnInint() {
this.store.dispatch(new UserDismissesEverything());
}
ngAfterViewInint() {
this.store.select(StatusBannerState).map(data => {
return data.status_banner;
}).subscribe(banner_state => {
if (banner_state.success_list.length > 0) {
this.showBanner = true;
this.bannerMessage = this.createSuccessBannerMessage(banner_state.success_list);
setTimeout(() => {
this.store.dispatch(new BannerDimissesSuccessMessage());
this.bannerMessage = this.createErrorBannerMessage(banner_state.error_list);
}, 5000);
} else if (banner_state.error_list.length > 0) {
this.bannerMessage = this.createErrorBannerMessage(banner_state.error_list);
} else {
this.showBanner = false;
this.bannerMessage = '';
}
});
}
I'm working on Ionic 2 project and I want to implement drag and drop feature. For that, I used bellow event in Ionic 2
<div (press) = "onDragInit(item, $event)"
(panstart)="dragStart($event)"
(panup)="onDrag($event)"
(pandown)="onDrag($event)"
(panend)="onDragEnd($event)"
(pressup)="pressUpEvent($event)">
</div>
The problem is panup and pandown events are not working for the first time.
If we did a horizontal move first then both events are working properly.
But if we did a vertical move first both events are not working until doing a horizontal move.
Has anyone faced with this problem?
this is my .ts file
public onDragInit(doc, event): void {
if(!doc.isSelected){
return;
}
// hide selected docs when start the drag
this.docs.forEach( (doc: any) => {
if(doc.isSelected){
doc.dragging = true;
this.draggingDocs.push(doc);
}else{
doc.dragging = false;
}
});
this.dragPoint = this.getDragPoint(event.center.x, event.center.y);
this.docDragging = true;
this.destination = this.getDroppableDoc(event.center.x,event.center.y);
event.preventDefault()
}
public dragStart(event: any): void {
if(!this.docDragging){
return ;
}
event.preventDefault();
}
public onDrag(event: any):void {
if(!this.docDragging){
return ;
}
this.dragPoint = this.getDragPoint(event.center.x, event.center.y);
let placeForDrop = this.getDroppableCar(event.center.x, event.center.y);
if(placeForDrop != null && placeForDrop.doc != null){
this.destination = placeForDrop;
}
event.preventDefault();
}
public onDragEnd(event: any): void {
if(this.destination && this.destination.doc){
this.onDrop.emit({draggingDocs: this.draggingDocs,destination: this.destination});
}
this.cancelDragging();
event.preventDefault();
}
public pressUpEvent(event: any): void {
this.cancelDragging();
event.preventDefault();
}
I found a solution for this. Angular 2 provides a token called HAMMER_GESTURE_CONFIG which accepts a HammerGestureConfig type.
In the simplest way, we can extend HammerGestureConfig like this.
// override default hammer.js settings.
import { HammerGestureConfig } from "#angular/platform-browser";
export class MCrewHammerConfig extends HammerGestureConfig {
public overrides = {
"pan": { direction: 30 },
"press": { time: 300 }
};
}
and add this to providers.
providers: [
{ provide: HAMMER_GESTURE_CONFIG, useClass: MCrewHammerConfig },
]
for more details angular-2-events.