Ionic 2 **panup** and **pandown** event are not working - javascript

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.

Related

Angular dynamic localisation and facebook.sdk does not update the translation for the Like button

I have added the Facebook js-sdk as a directive in an angular app, I have a button the switch the pages language my problem is that the sdk does not update the text for the Like button, even after I removed the sdk and add a new one for the selected language. I ran the FB.XFBML.parse() to update the txt but it will keep on using the first selected language only after a page refresh would changes take place
UPDATED CODE
Now Using a service with ngrx when language change it will replace the Facebook SDK for that language and dispatches an event for any the page directives to remove all the tags/classes Facebook added on the like button element and clear its children. Everything works the button show up but its still in the first language selected it does not change language
Code Service
#Injectable()
export class FacebookService {
constructor(private window: any, private document, private store: Store<fromRoot.State>) {
store.pipe(select(fromCore.getSelectedLang)).subscribe(lang => this.switchScript(lang));
if (!this.window.fbAsyncInit) {
this.window.fbAsyncInit = () => {
this.window.FB.init({
appId: environment.appId,
autoLogAppEvents: true,
cookie: true,
xfbml: true,
version: 'v4.0',
});
};
}
}
switchScript(lang: string) {
const langUrl = lang === 'ar' ? 'ar_AR' : 'en_US';
const newScript = document.createElement('script');
newScript.id = 'facebook-sdk';
newScript.async = true;
newScript.src = `https://connect.facebook.net/${langUrl}/sdk.js`;
const scriptTag = this.document.getElementById('facebook-sdk');
if (scriptTag) {
scriptTag.parentNode.replaceChild(newScript, scriptTag);
} else {
this.document.body.appendChild(newScript);
}
this.store.dispatch(SocialAction.UpdateTags({lang}));
}
}
Code Directive
#Directive({selector: '[lyxFacebook]'})
export class FacebookDirective implements AfterViewInit, OnDestroy {
tag$: Subscription;
constructor(private window: any,private document, private store: Store<fromRoot.State>) {
this.tag$ = store.pipe(select(Core.getTagLang)).subscribe(lang=> this.update(lang));
}
ngAfterViewInit(): void {
if (this.window.FB) {
this.window.FB.XFBML.parse();
}
}
update(lang: string) {
if (this.window.FB && lang) {
const tags = this.document.getElementsByClassName('fb-like');
if (tags && tags.length) {
for (let i = 0; i < tags.length; i++) {
tags[i].removeAttribute('fb-xfbml-state');
tags[i].removeAttribute('fb-iframe-plugin-query');
tags[i].classList.remove('fb_iframe_widget');
tags[i].innerHTML = '';
}
this.window.FB.XFBML.parse();
}
}
}
ngOnDestroy(): void {
if (this.tag$) {
this.tag$.unsubscribe();
}
}
}

Javascript constructor calls

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 = '';
}
});
}

Ionic 3 : Close modal with phone's back button

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

LassoJS and Marko-WIdgets

So guys, I'm in a bit little nightmare here. Starting using makoJs and Marko-widgets loving so far. But...
This is the thing I follow the organization of some samples and integrate with the lassoJS. So in the lasso way of doing things I do not get to implement the define component methods.
So what I need to accomplish:
module.exports = require('marko-widgets').defineComponent({
template: require('./template.marko'),
getInitialState: function(input) {
return {
name: input.name,
selected: input.selected || false;
}
},
getTemplateData: function(state, input) {
var style = ;
return {
name: state.name,
color: state.selected ? 'yellow' : 'transparent'
};
},
handleClick: function() {
this.setState('selected', true);
},
isSelected: function() {
return this.state.selected;
}
});
My Marko file is being writing as this:
import './style.css'
static function getClassNameForValue(value) {
if (value < 0) {
return 'negative';
} else if (value > 0) {
return 'positive';
}
}
class {
onInput(input) {
var value = input.value || 0;
this.state = {
value: value
};
}
handleIncrementClick(delta) {
this.state.value += delta;
var value = this.state.value;
var send = {
value:value
}
console.log(value);
$.post( "/tryPost", send,function( data ) {
console.log(data);
});
}
handleInputKeyUp(event, el) {
var newValue = el.value;
if (/^-?[0-9]+$/.test(newValue)) {
this.state.value = parseInt(newValue, 10);
}
}
}
$ var value=state.value;
<div class=['number-spinner', getClassNameForValue(value)]>
<button type="button" onClick("handleIncrementClick", -1)>
-
</button>
<input type="text" value=state.value size="4"
onKeyUp("handleInputKeyUp")>
<button type="button" onClick("handleIncrementClick", 1)>
+
</button>
</div>
Edit:
So I was thinking, know what version of those modules I'm using could help.
"lasso": "^2.11.3",
"lasso-less": "^2.4.3",
"lasso-marko": "^2.2.2",
"lodash": "^4.17.4",
"markdown-js": "0.0.3",
"marked": "^0.3.6",
"marko": "^4.0.0-rc.18",
"marko-widgets": "^6.6.0"
So how, to implement the listener for events of the lifecycle?
A small detail, but it has to do with events, so maybe:
<button type="button" onClick("handleIncrementClick", -1)>
I think the event is named on-click
I'm not quite sure what the question is, but with marko v4, marko-widgets should no longer be installed (only marko should be installed). You'll want to do the following:
npm uninstall marko-widgets --save
We are still in the process of finalizing the v4 documentation, but maybe the following v4 docs on component lifecycle methods would help: https://github.com/marko-js/marko/blob/9b6a288d83fef926590f24368a40476c5ff0e240/docs/06-components.md#lifecycle
If things are still unclear, please join in the Gitter chat room: https://gitter.im/marko-js/marko

Aurelia Google SignIn Button

I just started using Aurelia and I am having a problem with Google Sign in. It looks like I might be able to create my own Google button but I'd rather get it to work this way if it is possible. Here is my code:
<script src="https://apis.google.com/js/platform.js" async defer></script>
...
<body aurelia-app="src/main">
...
<span id="googleButtonPlaceholder" class="g-signin2" data-onsuccess="onSignIn"></span>
I have the function setup in my Aurelia class but I do not know if/how I can call it. I have tried ${onSignIn()} which just calls the function when it loads, ${onSignIn}, onSignIn(), onSignIn, data-onsuccess.bind="onSignin()" but nothing seems to work. Is there a way to pass the Aurelia function to the Google data-onsuccess attribute?
As a note, I am switching from Angular 1.5.8 where this previously worked.
Here's an example: https://gist.run?id=5da90f48b43b9c5867c8d2ace0f6371f
app.html
<template>
<require from="google-signin-button"></require>
<google-signin-button success.call="signinSuccess(googleUser)"
error.call="signinError(error)">
</google-signin-button>
<h1>${message}</h1>
</template>
app.js
export class App {
message = 'Not signed in.';
signinSuccess(googleUser) {
const name = googleUser.getBasicProfile().getName();
this.message = `Signed in: ${name}`;
}
signinError(error) {
this.message = `Error: ${error}`;
}
}
google-signin-button.js
import {inject, noView, bindable} from 'aurelia-framework';
const googleSigninClientID = '927519533400-mfupo3lq9cjd67fmmvtth7lg7d8l50q9.apps.googleusercontent.com';
function preparePlatform() {
// https://developers.google.com/identity/sign-in/web/build-button
// The name of the global function the platform API will call when
// it's ready.
const platformCallbackName = 'setGooglePlatformReady';
// An "API ready" promise that will be resolved when the platform API
// is ready.
const ready = new Promise(
resolve => window[platformCallbackName] = resolve);
// Inject the client id meta tag
const meta = document.createElement('meta');
meta.name = 'google-signin-client_id';
meta.content = googleSigninClientID;
document.head.appendChild(meta);
// Inject an async script element to load the google platform API.
// Notice the callback name is passed as an argument on the query string.
const script = document.createElement('script');
script.src = `https://apis.google.com/js/platform.js?onload=${platformCallbackName}`;
script.async = true;
script.defer = true;
document.head.appendChild(script);
return ready;
}
const platformReady = preparePlatform();
#noView()
#inject(Element)
export class GoogleSigninButton {
#bindable success = googleUser => { };
#bindable error = error => { };
#bindable scope = 'profile email';
#bindable theme = 'dark';
#bindable width = 240;
#bindable height = 50;
constructor(element) {
this.element = element;
}
attached() {
platformReady.then(this.renderButton);
}
renderButton = () => {
gapi.signin2.render(this.element, {
scope: this.scope,
width: this.width,
height: this.height,
longtitle: true,
theme: this.theme,
onsuccess: googleUser => {
console.info(googleUser);
this.success({ googleUser });
},
onfailure: error => {
console.error(error);
this.failure({ error });
}
});
}
}
#JeremyDanyow had a great answer but after I went to bed and read a little more about Aurelia, I thought of a solution to try before seeing his answer so I thought I'd share an alternate approach for those interested.
index.html
<main aurelia-app="src/main">
</main>
<script src="https://apis.google.com/js/platform.js" async defer></script>
app.html
<template>
<span id="my-signin2"></span>
<!-- other stuff -->
</template>
app.js
attached() {
this.render();
}
render() {
gapi.signin2.render('my-signin2', {
'scope': 'profile email',
'theme': 'dark',
'onsuccess': this.onSuccess,
'onfailure': this.onFailure
});
}
onSuccess(googleuser) {
let gUser = googleuser.getBasicProfile(),
id_token = googleuser.getAuthResponse().id_token;
}
onFailure(error) {
console.log(error);
}
This approach differs slightly from what Google shows on their website where they have you give platform.js an onload function to render the button. Instead, I create the button in the template and then once the template is done being loaded, attached() is called, which in turn, calls the function I would have had platform.js call onload.
Try data-onsuccess.call="onSignIn()".
After following #JeremyDanyow's example around a few corners I came up with this
It works ok for simple usage, but needs help...
when there is another window open using a google login there is an error loading something in the iframe google adds (this doesn't seem to break it)
the listeners don't work for more than a couple of login/logouts at most
Here's hoping that someone else can improve upon this.
google-signin-button.js
import { inject, noView, bindable } from 'aurelia-framework';
import { LogManager } from 'aurelia-framework';
const Console = LogManager.getLogger('google-signin-button');
// Integrating Google Sign-In into your web app
// https://developers.google.com/identity/sign-in/web/reference
// https://console.developers.google.com/apis/credentials
// inspiration: https://developers.google.com/identity/sign-in/web/build-button
function preparePlatform(): Promise<Function> {
// Inject an async script element to load the google platform API.
const script = document.createElement('script');
script.src = `https://apis.google.com/js/platform.js?onload=gapi_ready`;
script.async = true;
script.defer = true;
document.head.appendChild(script);
// return a promise that will resolve with the onload callback
return new Promise(resolve => window['gapi_ready'] = resolve);
}
#noView
#inject(Element)
export class GoogleSigninButton {
#bindable authenticated = (signedIn: Boolean) => { };
#bindable authorized = (GoogleUser: any) => { };
#bindable scope = 'profile email';
#bindable clientId = 'none';
#bindable theme = 'dark';
#bindable width = 240;
#bindable height = 50;
public element: Element;
constructor(element) {
this.element = element;
}
public wasAuthenticated: Boolean;
sendAuthenticated(signedIn: Boolean) {
if (signedIn !== this.wasAuthenticated) {
this.authenticated(signedIn);
this.wasAuthenticated = signedIn;
}
}
public wasAuthorized: any;
sendAuthorized(googleUser: any) {
if (googleUser !== this.wasAuthorized) {
this.authorized(googleUser);
this.wasAuthorized = googleUser;
this.sendAuthenticated(true);
}
}
attached() {
// inject the script tag
preparePlatform()
.then(() => {
// load the auth lib
// Console.debug('gapi created, loading auth2');
window['gapi'].load('auth2', () => {
// init the auth lib
// Console.debug('gapi.auth2 loaded, intializing with clientId:', this.clientId);
window['gapi'].auth2.init({
client_id: this.clientId
})
.then(
(googleAuth: any) => {
// Console.debug('gapi.auth2 intialized');
// listen for user signed in/out
googleAuth.isSignedIn.listen((signedIn: Boolean) => {
// Console.debug('googleAuth.isSignedIn.listener', signedIn);
this.sendAuthenticated(signedIn);
});
// listen for who signed in
googleAuth.currentUser.listen((googleUser: any) => {
// Console.debug('googleAuth.currentUser.listener', googleUser);
this.sendAuthorized(googleUser);
});
// draw the button
window['gapi'].signin2.render(this.element, {
scope: this.scope,
width: this.width,
height: this.height,
longtitle: true,
theme: this.theme,
onsuccess: (googleUser: any) => {
// Console.debug('gapi.signin2.render success', googleUser);
this.sendAuthorized(googleUser);
},
// drawing button failure
onfailure: (error: any) => {
Console.error('gapi.signin2.render failure', error);
}
});
},
// intialization error
(errObj: any) => {
Console.error('gapi.auth2.init -> errObj', errObj);
}
);
});
});
}
}
some-usage.js
import environment from '../environment';
import { LogManager } from 'aurelia-framework';
const Console = LogManager.getLogger('Login');
import { inject } from 'aurelia-framework';
import { AuthService } from 'aurelia-authentication';
import { EventAggregator } from 'aurelia-event-aggregator';
import './login.scss';
#inject(AuthService, EventAggregator)
export class Login {
public authService: AuthService;
public eventAggregator: EventAggregator;
public googleSigninClientID: string = 'none';
constructor(authService: AuthService, eventAggregator: EventAggregator) {
this.eventAggregator = eventAggregator;
this.authService = authService;
this.googleSigninClientID = environment.googleSigninClientID;
};
isAuthenticated(signedIn: Boolean) {
Console.warn('isAuthenticated', signedIn);
}
isAuthorized(googleUser: any) {
Console.warn('isAuthorized', googleUser);
}
}
some-usage.html
<template>
<require from="../resources/elements/google-signin-button"></require>
<section>
<div class="container-fluid">
<center>
<google-signin-button client-id.bind="googleSigninClientID" authenticated.bind="isAuthenticated" authorized.bind="isAuthorized"> </google-signin-button>
</center>
</div>
</section>
</template>

Categories

Resources