When using the code below and entering the address index.html#players I am not taken to the players route, in fact nothing happens at all. However, if I open up the dev tools and run Parse.history.checkUrl() it works as expected. When I remove Parse.history.start() and do it manually I get TypeError: undefined is not a function.
$(() ->
$wrapper = $('#wrapper')
Router = Parse.Router.extend({
routes: {
'selected': 'selected'
'players': 'players'
'': 'teams'
}
selected: () ->
console.log('selected')
$wrapper.removeClass()
$wrapper.addClass('selected')
players: () ->
console.log('players')
$wrapper.removeClass()
$wrapper.addClass('players')
teams: () ->
console.log('teams')
$wrapper.removeClass()
$wrapper.addClass('teams')
})
window.router = new Router()
Parse.history.start()
)
If anyone else is having this problem and urgently needs a work-around I have found that the code below works.
window.router = new Router()
try
Parse.history.start({})
catch err
console.log(err)
Parse.history.checkUrl()
window.onhashchange = Parse.history.checkUrl
Related
I create an Application to Read and Update Contacts Details. Here is a problem to updating Contact email. (I'm using Ionic 3)
When I try to add information to an existing contact the app closes and the console dont show nothing more. I'm using android studio to see the APK in the mobile and does not allow me to update. Here my code:
Update: I got the follow error:
"Wrong type for parameter "properties" of contacts.create: Expected Object, but got String."
"Error in Success callbackId: Contacts1616016237 : TypeError: Wrong type for parameter "properties" of contacts.create: Expected Object, but got String."
I pass the id as a parameter and I look for the contact to update.
UpdateContact(id, email){
var options = new ContactFindOptions();
options.filter = id;
options.multiple = true;
let proms = [];
this.contacts.find(["id"], options).then(res=>{res.forEach( (item:Contact) => {
//console.log(contact);
proms.push(new Promise( (resolve, reject) => {
var f = new ContactField('email',email,true);
item.emails = [];
item.emails.push(f);
console.log('FIXED '+item.displayName);
item.save().then(() => console.log('Contact saved!'),
(error: any) => console.error('Error saving contact.', error)
);
resolve();
}))
})
})
}
I'm trying to figure out the "correct" way to set up push notifications on an Ionic v3 app using the OneSignal SDK and native plugin (iOS is all I care about, for the moment). My goal is to set up an observer using the addSubscriptionObserver hook provided by the plugin, and update my database with the userId when the user opts in to notifications. I believe the problem I'm having has to do with the scope the callback is running in. I am trying to access the userService (injected into the component where the subscriptionObserver is added), but I am getting the following error when the callback runs:
2018-04-22 09:59:53.977213-0700 WodaX[2610:692168] Error in Success callbackId: OneSignalPush492317370 : TypeError: undefined is not an object (evaluating 'this.userService.updateUserOneSignalId')
Here is my code:
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.statusBar.overlaysWebView(false);
this.keyboard.disableScroll(false);
this.splashScreen.hide();
// OneSignal Code start:
// Enable to debug issues:
//window["plugins"].OneSignal.setLogLevel({logLevel: 4, visualLevel: 4});
let notificationOpenedCallback = function(jsonData) {
console.log('notificationOpenedCallback: ' + JSON.stringify(jsonData));
};
let iosSettings = {};
iosSettings["kOSSettingsKeyAutoPrompt"] = false;
window["plugins"].OneSignal
.startInit("[MY_ONE_SIGNAL_APP_ID]")
.handleNotificationOpened(notificationOpenedCallback)
.inFocusDisplaying(window["plugins"].OneSignal.OSInFocusDisplayOption.Notification)
.iOSSettings(iosSettings)
.endInit();
window["plugins"].OneSignal.addPermissionObserver(this.handlePermissionChange);
window["plugins"].OneSignal.addSubscriptionObserver(this.handleSubscriptionChange);
});
}
openPage(page) {
this.nav.setRoot(page.component);
}
private handleSubscriptionChange(data: any) {
console.log(data)
if (data.to.userSubscriptionSetting && data.to.userId) {
let userUuid = "testId"
this.userService.updateUserOneSignalId(userUuid, data.to.userId).subscribe((res) => {
console.log(res);
}, (err) => {
console.log(err);
});
}
}
The same call to the userService method works in a the getIds callback in a different component, so I'm guessing this has something to do with how the callbacks are registered by the addSubscriptionObserver method.
Here is the operative plugin code:
OneSignal.prototype.addSubscriptionObserver = function(callback) {
OneSignal._subscriptionObserverList.push(callback);
var subscriptionCallBackProcessor = function(state) {
OneSignal._processFunctionList(OneSignal._subscriptionObserverList, state);
};
cordova.exec(subscriptionCallBackProcessor, function(){}, "OneSignalPush", "addSubscriptionObserver", []);
}
I'd appreciate insight from anyone who may have successfully set this up. The goal is to be able to store individual OneSignal Ids so users can trigger notifications to other users. I can do this now, but only if I do it when the user accepts the prompt. I need to be able to do it anytime they opt in to push notifications, even from the settings after declining the original prompt.
So you have faced pretty common pitfall handling 'this' during a call of a function with a callback method.
Normally if you see those "undefined" type of errors you want to console.log 'this' (console.log(this)) to see which scope 'this' points at and then decide a fix.
In your case I would use fat arrow function assignment for handleSubscriptionChange method:
instead: handleSubscriptionChange(data:any) => {...}
do: handleSubscriptionChange = (data:any) => {...}
Fat arrow function doesn't create its own 'this' and in this case should solve you problem.
I am calling a simple google api using an HTTP method on the server. It appears I am getting a json object back, yet the callback on the client seems to return an undefined object.
My guess is somehow the result isn't making it to the callback in time. A bit confused.
Full code here:
if Meteor.isClient
Meteor.startup () ->
console.log "Client Started."
Meteor.call("getGeocode", 94582, (error, result) ->
console.log "GeoCode returned to client, #{result}."
Session.set("latitude", result))
Template.results.latitude = () ->
Session.get("latitude")
Template.results.longitude = () ->
"longitude"
if Meteor.isServer
Meteor.startup () ->
console.log "Server Started"
Meteor.methods
"getGeocode": (zipCode) ->
result = HTTP.call("GET", "http://maps.googleapis.com/maps/api/geocode/json?address=#{zipCode}&sensor=false")
console.log "Geocode called, returning #{result}."
Your getGeocode method is returning undefined because CoffeeScript will automatically return the result last statement in the function, which in this case is a console.log.
I don't think result is really want you want though. I recommend including util at the start of your isServer section like so:
if Meteor.isServer
util = Npm.require 'util'
Now you can call console.log util.inspect result, {depth: null} to see what it's made of. I think what you may actually want to return is result.data.results[0]. Your code could look something like:
if Meteor.isClient
Meteor.startup () ->
console.log "Client Started."
Meteor.call("getGeocode", 94582, (error, result) ->
Session.set("latitude", result.geometry.location.lat))
Template.results.latitude = () ->
Session.get("latitude")
Template.results.longitude = () ->
"longitude"
if Meteor.isServer
util = Npm.require 'util'
Meteor.startup () ->
console.log "Server Started"
Meteor.methods
"getGeocode": (zipCode) ->
result = HTTP.call("GET", "http://maps.googleapis.com/maps/api/geocode/json?address=#{zipCode}&sensor=false")
geoData = result.data.results[0]
console.log util.inspect geoData, {depth: null}
geoData
This is the strangest thing, for some reason even with autopublish turned on, I cannot access the collection from browser console. The code below is a simple list program where you can enter items into the collection and it will appear as a list on the screen. In console when I try to access the database by typing People.find() or People.find().fetch() it brings up an error 'ReferenceError: Can't find variable: People'
How come this is happening I have autopublish on, so I thought I can access the collection from the client?
Code:
var People = new Meteor.Collection("people");
if (Meteor.isClient) {
console.log(People.find());
Template.personList.people = function () {
return People.find();
};
Template.personForm.events({
'click button': function(e, t) {
var el = t.find("#name");
People.insert({ name: el.value });
el.value = "";
}
});
Template.person.editing = function () {
return Session.get("edit-" + this._id);
};
Template.person.rendered = function () {
var input = this.find("input");
if(input) {
input.focus();
}
};
Template.person.events({
'click .name': function (e, t) {
Session.set("edit-" + t.data._id, true);
},
'keypress input': function (e, t) {
if (e.keyCode == 13) {
People.update(t.data._id, { $set: { name: e.currentTarget.value }});
Session.set("edit-" + t.data._id, false);
}
},
'click .del': function (e, t) {
People.remove(t.data._id);
}
});
}
You don't have to use # unless you're using coffeescript. In plain javascript remove the var so your variable can be accessed anywhere outside of the file (including the chrome console):
var People = new Meteor.Collection("people");
becomes
People = new Meteor.Collection("people");
To use coffeescript use a .coffee extension and run meteor add coffeescript to allow meteor to compile coffeescript files to js files
to answer your question # is used for CoffeeScript (Javascript Alternative), you can add the meteor package for it and then write your app in that language. Learn about it here http://coffeescript.org
I've tried to understand this post regarding this concept, however, I'm failing to get it. I have the following simple setup:
/server/test.js
Meteor.methods({
abc: function() {
var result = {};
result.foo = "Hello ";
result.bar = "World!";
return result;
}
});
/client/myapp.js
var q = Meteor.call('abc');
console.log(q);
This structure returns to the console undefined.
If I change the myapp.js file to:
Meteor.call('abc', function(err, data) {
!err ? console.log(data) : console.log(err);
}
I receive the Object in my console.
Ideally this is what I'd like to be able to do, but it doesn't work, stating in the console: Cannot read property 'greeting' of undefined
/client/myapp.js
var q = Meteor.call('abc');
Template.hello.greeting = function() {
return q.foo;
}
Any help in passing the data from the server object into the template would be greatly appreciated. I'm still learning JavaScript & Meteor.
Thanks!
From the Meteor.call documentation:
On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method. That is because the client doesn't have fibers, so there is not actually any way it can block on the remote execution of a method.
So, you'll want to do it like this:
Meteor.call('abc', function(err, data) {
if (err)
console.log(err);
Session.set('q', data);
});
Template.hello.greeting = function() {
return Session.get('q').foo;
};
This will reactively update the template once the data is available.
This happens because Npm.require has Async behavior. That's the reason that you have to write a callback for Meteor.call.
But there is a solution, just use install(mrt add npm) and you'll get a function named Meteor.sync(//...) with this you can do both games: sync and async in your Meteor.call().
Reference: http://www.sitepoint.com/create-a-meteor-app-using-npm-module/
You can get the return value of a Meteor method for use in a template by using a reactive variable. Check out the working demonstration on Meteorpad
I went for a ghetto solution. But, it works for me, which is what matters, to me. Below is my code, which, in concept, I think, solves OP's problem.
In the client's main.js:
Meteor.setInterval(function() {
confirmLogin();
}, 5000);
This runs the confirmLogin() function every five seconds.
The confirmLogin function (in the client's main.js):
function confirmLogin() {
Meteor.call('loggedIn', function (error, result) {
Session.set("loggedIn", result);
});
}
The loggedIn method (in the server's main.js):
loggedIn: function () {
var toReturn = false;
var userDetails = Meteor.user();
if (typeof userDetails["services"] !== "undefined") {
if (typeof userDetails["services"]["facebook"] != "undefined") {
toReturn = true;
}
}
return toReturn;
},
The relevant helper:
loggedIn: function () {
return Session.get("loggedIn");
}