Integrate the pull to refresh feature in Ionic 3 with Wordpress - wordpress

I'm working on a Ionic3 app integrated with Wordpress using REST API v2 and I need to include the pull to refresh feature but I don't understand how to do it with my code.
This is my function that retrieves my post
getPostsWordpress(){
if(!(this.posts.length > 0)){
let loading = this.loadingCtrl.create();
loading.present();
this.wordpressService.getRecentPostsWithSort(this.categoryId,this.sort)
.subscribe(data => {
for(let post of data){
post.excerpt.rendered = post.excerpt.rendered.split('<a')[0] + "</p>";
this.posts.push(post);
}
loading.dismiss();
});
}
}
...
doInfinite(infiniteScroll) {
let page = (Math.ceil(this.posts.length/10)) + 1;
console.log("PAGE_"+page)
console.log("this.posts.length_"+this.posts.length)
let loading = true;
this.wordpressService.getRecentPostsWithSort(this.categoryId,this.sort, page)
.subscribe(data => {
for(let post of data){
if(!loading){
infiniteScroll.complete();
}
post.excerpt.rendered = post.excerpt.rendered.split('<a')[0] + "</p>";
this.posts.push(post);
loading = false;
}
}, err => {
this.morePagesAvailable = false;
})
}
doInfinite let me to implement infinite scroll, and all works well!
How is it possibile to integrate pull to refresh from the ionic documentation?
This is a sample from the doc and I don't understand how could I use it in my project.
doRefresh(refresher) {
console.log('Begin async operation', refresher);
setTimeout(() => {
console.log('Async operation has ended');
refresher.complete();
}, 2000);
}
Someone can help me?
Thank you in advance!

add this to ur html
<ion-refresher (ionRefresh)="doRefresh($event)">
<ion-refresher-content
pullingIcon="arrow-dropdown"
pullingText="Pull to refresh"
refreshingSpinner="circles"
refreshingText="Refreshing...">
</ion-refresher-content>
then in ur do refresh
doRefresh(refresher) {
console.log('Begin async operation', refresher);
//ur function e.g getPostWordPress()
setTimeout(() => {
console.log('Async operation has ended');
refresher.complete();
}, 2000);}

Related

Ionic 4, Firebase-x and FCM Push notification with action buttons

I am trying to add action buttons to the push notifications sent via the firebase admin SDK to my Ionic 4 app using the Firebase-X native plugin to handle push notifications. My app is running on android and ios.
Here's my current script that sends me successfully a push notification:
exports.sendDebugPush = functions.pubsub.schedule('* * * * *').onRun((context) => {
let promises: Promise<any>[] = [];
return admin.database().ref('/users/******').once("value")
.then( user => {
let todos = [];
for(let key in user.val().nextActions) {
if(user.val().nextActions[key].active != false) {
let todo = user.val().nextActions[key]
todo['todoid'] = key;
todos.push(todo);
}
}
if(todos.length > 0) {
//currently we pick a random todo, later on the one with the highest priority
//todos.sort((a, b) => (a.priority/1 < b.priority/1) ? 1 : -1);
let randomTodo = todos[Math.floor(Math.random()*todos.length)]
let payload: any = {
notification: {
title: "Gossik",
body: "Hoiiiii " + new Date().toISOString()
},
data: {
title: "Gossik",
body: "Hoiiiii " + new Date().toISOString(),
target: 'todo',
todoid: randomTodo.todoid
}
};
Object.values(user.val().devices).forEach( (device) => {
promises.push(admin.messaging().sendToDevice(String(device), payload));
});
}
return Promise.all(promises)
.then( () => {
console.log('success!');
})
.catch( error => {
console.log('failed :(');
console.log(error);
});
});
});
Of course, without action buttons. And this function handles the push notifications in my app (this.firebase = FirebaseX plugin imported from 'import { FirebaseX } from "#ionic-native/firebase-x/ngx";'):
initPushNotifications() {
this.firebase.getToken().then(token => {
this.db.saveDeviceToken(this.auth.userid, token);
});
this.firebase.onMessageReceived().subscribe(data => {
if(!data.target) {
let title = '';
if(data.title) {
title = data.title;
} else if(data.notification && data.notification.title) {
title = data.notification.title;
} else if(data.aps && data.aps.alert && data.aps.alert.title) {
title = data.aps.alert.title;
}
let body = '';
if(data.body){
body = data.body;
} else if(data.notification && data.notification.body){
body = data.notification.body;
} else if(data.aps && data.aps.alert && data.aps.alert.body){
body = data.aps.alert.body;
}
this.alertCtrl.create({
message: title + ' ' + body,
buttons: [
{
text: "Ok"
}
]
}).then( alert => {
alert.present();
});
} else {
this.goToToDoPage(data.todoid);
}
});
}
It does this also successfully. I achieved to handle the click on the push notification such that it redirects to my To-Do page for this kind of push notification (one with a 'target' property). But now I'd like to add two action buttons 'Start' and 'Skip' on the push notification to start or skip the corresponding to-do. To be clear, I am talking about a background push notification, so the app is not open. The user then gets a standard push notification on his phone and there I'd like two action buttons to take an action without opening the app itself.
I tried various things with the payload to first even show me action buttons, but didn't achieve it. For example, the following is not working for me:
let payload: any = {
notification: {
title: "Gossik",
body: "Hoiiiii " + new Date().toISOString()
},
data: {
title: "Gossik",
body: "Hoiiiii " + new Date().toISOString(),
target: 'todo',
todoid: randomTodo.todoid,
"actions": [
{ "icon": "approve_icon", "title": "APPROVE", "callback": "AppComponent.approve", "foreground": true},
{ "icon": "reject_icon", "title": "REJECT", "callback": "AppComponent.reject", "foreground": true}
]
}
};
Thanks a lot in advance for your help and let me know if something is still unclear. :)

Ionic refresher get's fired automatically on page load?

Ionic refresher seems to be refreshing the page without being manually calling the doRefresh. I would like the refresher to only execute when the "pull down" action is done.
Seems like doRefresh is executed on "ionviewdidload" function automatically.
<ion-refresher (ionRefresh)="doRefresh($event);">
<ion-refresher-content
pullingText="Pull to refresh" pullingIcon="arrow-dropdown"
refreshingSpinner="circles"
refreshingText="..fetching">
</ion-refresher-content>
</ion-refresher>
home.ts
doRefresh(refresher) {
console.log('the current tab that is set = ' + this.tabSelId);
console.log('testing');
this.user = JSON.parse(window.localStorage.getItem('user'));
let self_ = this;
let devicePos = null;
let devicelat = null;
let devicelong = null;
Geolocation.getCurrentPosition().then((position) => {
// self_.loadingData(devicePos);
devicelat = position.coords.latitude;
devicelong = position.coords.longitude;
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
refresher.complete();
}, (err) => {
console.log('failed to get lat and long :' + err);
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
// self_.filter_posts_by_type(self_.tabSelId);
// loading.dismiss();
// refresher.complete();
});
}
on my ionviewdidload function (home.ts):
ionViewDidLoad(){
this.user = JSON.parse(window.localStorage.getItem('user'));
let self_ = this;
let devicePos = null;
console.log('the current tab that is set = '+this.tabSelId);
let devicelat = null;
let devicelong = null;
Geolocation.getCurrentPosition().then((position) => {
devicelat = position.coords.latitude;
devicelong = position.coords.longitude;
console.log('%c executing when position is got successfully ', 'background: #222; color: #bada55');
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
console.log('executing when position is got successfully');
}, (err) => {
console.log('failed to get lat and long :' + err);
devicelat = 28.318237;
devicelong = 111.168137;
self_.get_all_posts(devicelat, devicelong, self_.tabSelId);
});
is it the default behaviour when using
"ion-refresher"
I would like the refresher to only fire when "pull down" action is done.
Don't know why the doRefresh() function is being executed when the app is loaded (the first time only)
In your Html use like..
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-refresher-content pullingIcon="arrow-dropdown" pullingText="Pull to refresh" refreshingSpinner="circles"
refreshingText="Refreshing...">
</ion-refresher-content>
</ion-refresher>
In .ts use like...
doRefresh(event) {
this.userPost();
setTimeout(() => {
event.target.complete();
}, 2000);
}

firebase reset password controller

Yesterday my app was launched, Ionic v1, and a few users entered the wrong password and can't log into the app.
The app uses firebase authentication. I have a __refs file that points to the database and have tried numerous things trying to get the reset to work.
I've tried referencing $firebaseAuth, of course my __refs, $firebase then use $firebase.auth()...
I didn't write the authentication of this app so I'm not real sure how it works. I'm hoping that someone can help me.
My reset controller
angular.module('formulaWizard').controller('ResetPasswordCtrl',
function($scope, $ionicLoading, $firebaseAuth, __Refs) {
$scope.user = {
email: ''
};
$scope.errorMessage = null;
var fbAuth = $firebaseAuth(__Refs.rootRef);
$scope.resetPassword = function() {
$scope.errorMessage = null;
$ionicLoading.show({
template: 'Please wait...'
});
fbAuth.sendPasswordResetEmail($scope.user.email)
.then(showConfirmation)
.catch(handleError);
};
function showConfirmation() {
$scope.emailSent = true;
$ionicLoading.hide();
}
function handleError(error) {
switch (error.code) {
case 'INVALID_EMAIL':
case 'INVALID_USER':
$scope.errorMessage = 'Invalid email';
break;
default:
$scope.errorMessage = 'Error: [' + error.code + ']';
}
$ionicLoading.hide();
}
});
My Refs file
angular.module('formulaWizard')
.factory('__Refs', function ($firebaseArray, $firebaseObject) {
// Might use a resource here that returns a JSON arrayf
var ref = new Firebase('https://firebasedatabase.com/');
return {
rootRef: ref,
customers: ref.child('customers'),
}
});
I can't take credit for the answer it was provide by Abimbola Idowu on HackHands.
Since I paid for the answer I thought I would share it with anyone else that might also be stumped by this.
$scope.resetPassword = function() {
$scope.errorMessage = null;
$ionicLoading.show({
template: 'Please wait...'
});
__Refs.rootRef.resetPassword({ email: $scope.user.email }, function(error) {
if (error === null) {
showConfirmation();
} else {
handleError()
}
});
};
This is the __refs service
angular.module('formulaWizard')
.factory('__Refs', function ($firebaseArray, $firebaseObject) {
// Might use a resource here that returns a JSON arrayf
var ref = new Firebase('https://firebasedatabase.com/');
return {
rootRef: ref,
}
});

Mongoose pre.save() async middleware not working on record creation

I am using keystone#0.2.32. I would like to change the post category to a tree structure. The below code is running well except when I create a category, it goes into a deadlock:
var keystone = require('keystone'),
Types = keystone.Field.Types;
/**
* PostCategory Model
* ==================
*/
var PostCategory = new keystone.List('PostCategory', {
autokey: { from: 'name', path: 'key', unique: true }
});
PostCategory.add({
name: { type: String, required: true },
parent: { type: Types.Relationship, ref: 'PostCategory' },
parentTree: { type: Types.Relationship, ref: 'PostCategory', many: true }
});
PostCategory.relationship({ ref: 'Post', path: 'categories' });
PostCategory.scanTree = function(item, obj, done) {
if(item.parent){
PostCategory.model.find().where('_id', item.parent).exec(function(err, cats) {
if(cats.length){
obj.parentTree.push(cats[0]);
PostCategory.scanTree(cats[0], obj, done);
}
});
}else{
done();
}
}
PostCategory.schema.pre('save', true, function (next, done) { //Parallel middleware, waiting done to be call
if (this.isModified('parent')) {
this.parentTree = [];
if(this.parent != null){
this.parentTree.push(this.parent);
PostCategory.scanTree(this, this, done);
}else
process.nextTick(done);
}else
process.nextTick(done); //here is deadlock.
next();
});
PostCategory.defaultColumns = 'name, parentTree';
PostCategory.register();
Thanks so much.
As I explained on the issue you logged on Keystone here: https://github.com/keystonejs/keystone/issues/759
This appears to be a reproducible bug in mongoose that prevents middleware from resolving when:
Parallel middleware runs that executes a query, followed by
Serial middleware runs that executes a query
Changing Keystone's autokey middleware to run in parallel mode may cause bugs in other use cases, so cannot be done. The answer is to implement your parentTree middleware in serial mode instead of parallel mode.
Also, some other things I noticed:
There is a bug in your middleware, where the first parent is added to the array twice.
The scanTree method would be better implemented as a method on the schama
You can use the findById method for a simpler parent query
The schema method looks like this:
PostCategory.schema.methods.addParents = function(target, done) {
if (this.parent) {
PostCategory.model.findById(this.parent, function(err, parent) {
if (parent) {
target.parentTree.push(parent.id);
parent.addParents(target, done);
}
});
} else {
done();
}
}
And the fixed middleware looks like this:
PostCategory.schema.pre('save', function(done) {
if (this.isModified('parent')) {
this.parentTree = [];
if (this.parent != null) {
PostCategory.scanTree(this, this, done);
} else {
process.nextTick(done);
}
} else {
process.nextTick(done);
}
});
I think it's a bug of keystone.js. I have changed schemaPlugins.js 104 line
from
this.schema.pre('save', function(next) {
to
this.schema.pre('save', true, function(next, done) {
and change from line 124 to the following,
// if has a value and is unmodified or fixed, don't update it
if ((!modified || autokey.fixed) && this.get(autokey.path)) {
process.nextTick(done);
return next();
}
var newKey = utils.slug(values.join(' ')) || this.id;
if (autokey.unique) {
r = getUniqueKey(this, newKey, done);
next();
return r;
} else {
this.set(autokey.path, newKey);
process.nextTick(done);
return next();
}
It works.

Switch to iframe with phantom.js

I would like to switch to an iframe using pure phantom.js code
Here is my first attempt
var page = new WebPage();
var url = 'http://www.theurltofectch'
page.open(url, function (status) {
if ('success' !== status) {
console.log("Error");
} else {
page.switchToFrame("thenameoftheiframe");
console.log(page.content);
phantom.exit();
}
});
It produces only the source code of the main page. Any idea ?
Notice that the iframe domain is different from the main page domain.
Please give this a try I believe it may be an async issues meaning the iframe is not present when trying to access it. I received the below snippet from another post.
var page = require('webpage').create(),
testindex = 0,
loadInProgress = false;
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onLoadStarted = function() {
loadInProgress = true;
console.log("load started");
};
page.onLoadFinished = function() {
loadInProgress = false;
console.log("load finished");
};
/*
page.onNavigationRequested = function(url, type, willNavigate, main) {
console.log('Trying to navigate to: ' + url);
console.log('Caused by: ' + type);
console.log('Will actually navigate: ' + willNavigate);
console.log('Sent from the page\'s main frame: ' + main);
};
*/
/*
The steps array represents a finite set of steps in order to perform the unit test
*/
var steps = [
function() {
//Load Login Page
page.open("https://www.yourpage.com");
},
function() {
//access your iframe here
page.evaluate(function() {
});
},
function() {
//any other step you want
page.evaluate(function() {
});
},
function() {
// Output content of page to stdout after form has been submitted
page.evaluate(function() {
//console.log(document.querySelectorAll('html')[0].outerHTML);
});
//render a test image to see if login passed
page.render('test.png');
}
];
interval = setInterval(function() {
if (!loadInProgress && typeof steps[testindex] === "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] !== "function") {
console.log("test complete!");
phantom.exit();
}
}, 50);
replace
console.log(page.content);
with
console.log(page.frameContent);
Should return the contents of the frame phantomjs switched to.
If the iframe is from another domain you may need to add the --web-security=no option like this:
phantomjs --web-security=no myscript.js
As an additional information, what xMythicx said could be true. Some iframes are rendered via Javascript after page finishes loading. If the iframe contents are empty, then you will need to wait for all resources to finish loading, before you start grabbing stuff from the page. But this is another issue, if you need an answer on this, I suggest you ask a new question about it, and I will answer there.
Had the same problem for iframes and
phantomjs --web-security=no
helped in my case :]

Resources