Meteor IronRouter waitOn Infinite loop - meteor

I have a pretty standard setup for my meteor app using IronRouter. What I am having problems with is this, I am attempting to redirect someone to a page based on some tokens in a url coming from a third party website but when the user is sent to their destination from the Accounts.onLogin callback via Router.go("some/fun/url"); the waitOn function runs endlessly.
Below is the pertinent part of the setup.
First the route that I am redirecting to:
Router.route("/shows/:show_acronym/sponsorships", {
name:"sponsorshipsSalesPortal",
data:function(){
return {show:Shows.findOne({acronym:this.params.show_acronym})};
},
waitOn:function(){
console.log("wait on");
return [Meteor.subscribe("show_by_acronym",this.params.show_acronym),Meteor.subscribe("catalogue_products_by_acronym", this.params.show_acronym)];
}
});
Next the relevant part of the onLogin hook:
Accounts.onLogin(function(){
if (Session.get("showToRedirectTo")){
console.log("sending to sponsorship portal");
var ur ="/shows/"+Session.get("showToRedirectTo")+"/sponsorships"
return Router.go(ur);
}
});
When it hits the redirect, the url changes and the message "wait on" prints in the console forever. Does anyone know of a solution to this? I would prefer to keep all of my subscriptions at the router level if at all possible.
Thanks

You should only return subscription cursors (Meteor.subscribe(*)) in the waitOn return array.
In your case, "this.params.show_acronym" is the problem...

Actually your code looks good, its been a while since i dont use Iron Router or Sessions.
But looking at the WaitOn, it seems okay, the problem can come from the Server side where show_by_acronym or catalogue_products_by_acronym its throwing an error, but in all the cases this should cause you to get a spinner loading forever, not a console.log("wait on"); printed forever.
so i think your Accounts.onLogin is causing this.
Try something like.
Accounts.onLogin(function(){
if (Session.get("showToRedirectTo")){
console.log("sending to sponsorship portal");
var ur ="/shows/"+Session.get("showToRedirectTo")+"/sponsorships"
Router.go(ur);
Session.set('showToRedirectTo', false)
}
});

Related

$http returning error response NULL on first call after launch (ionic) everytime, but after subsequent http post its ok

Whenever I launch my app, and click on login on the first few tries, the login will attempt a POST http to the server. However $http always (everytime) returns NULL on first try. sometimes after several few tries still NULL if done fast. But subsequently, its all ok.
I dont get it, why is $http returning error response NULL initially ??
Here is my login controller doing the http post
Login Controller (LoginCtrl)
https://gist.github.com/anonymous/771194bc5815e4ccdf38b57d6158853f
var req = {
method: 'POST',
url: baseURL,
data: postObject,
//timeout: 5000
};
err is NULL here:
}).error(function(err) {
I dont know if it is CORS but I'ved got this set in config.xml
<access origin="*" />
my config.xml
https://gist.github.com/anonymous/b2df3a857338d14ec3fcd6dda776e212
Any ideas ?
Im using ionic 1.7.14
on device iOS 9.3.1
UPDATE
I'ved put the problem code here. can logout first to goto login screen. enter in anything in username/password field, click login once failed, second or third try will be success.
https://github.com/axilaris/ionic_null_http_problem
some troubleshooting so far: i noticed the http post request is called twice. not sure why.
UPDATED the code using $http.post.then but still has the same effect
$http.post(baseURL, postObject).then(function successCallback(response)
response has NULL data --> Object {data: null, status: 0, config: Object, statusText: ""}
It is hard to diagnose having the above details only.
However the problem could be that your handler (login function) is triggered before digest cycle finished updating $scope.data.username and $scope.data.password and for the first tries it sends empty values for those to the server and works fine later.
You can run Safari web inspector to see what is sent to the server to prove this.
The fix may depend on how your view/template is coded. Can you please share it? Or, ideally, create a working sample at http://play.ionic.io/
Another option to fix could be to try to wrap your code related to http request into
$timeout(function() {
// your code goes here
});
or, consider using .$applyAsync() (see the docs for details)
This might help to fix the problem
You are probably getting this inconsistent behavior as you are using the 'success' promise method instead of 'then' (note that use of the success method has now been deprecated).
The key differences between these two methods are:
then() - full power of the promise API but slightly more verbose
success() - doesn't return a promise but offeres slightly more convienient syntax
as highlighted in this answer.
Hence in your scenario, instead of using 'success':
var req = {
method: 'POST',
url: baseURL + 'session/login',
data: postObject,
//timeout: 5000
};
$http(req).success(function(resp) {...
use 'then' along with angular's post shortcut method (you don't have to use this shortcut method, but I think it makes the code more succinct) e.g.:
$http.post(baseURL + 'session/login', postObject).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Using 'then' returns a promise resolved with a value returned from a callback, so it should give you a consistently valid result.
it was a timeout in app.js that caused it. was set to 1 second which gives it it arbitrary success rate.
config.timeout = 1000;

Meteor: send message to user at hot code push

How can I let the user know when they are getting a hot code push?
At the moment the screen will go blank during the push, and the user will feel it's rather weird. I want to reassure them the app is updating.
Is there a hook or something which I can use?
Here's the shortest solution I've found so far that doesn't require external packages:
var ALERT_DELAY = 3000;
var needToShowAlert = true;
Reload._onMigrate(function (retry) {
if (needToShowAlert) {
console.log('going to reload in 3 seconds...');
needToShowAlert = false;
_.delay(retry, ALERT_DELAY);
return [false];
} else {
return [true];
}
});
You can just copy that into the client code of your app and change two things:
Replace the console.log with an alert modal or something informing the user that the screen is about to reload.
Replace ALERT_DELAY with some number of milliseconds that you think are appropriate for the user to read the modal from (1).
Other notes
I'd recommend watching this video on Evented Mind, which explains what's going on in a little more detail.
You can also read the comments in the reload source for further enlightenment.
I can image more complex reload logic, especially around deciding when to allow a reload. Also see this pacakge for one possible implementation.
You could send something on Meteor.startup() in your client-side code. I personally use Bert to toast messages.

Ember-Pouch not syncing?

I like to fix the cross brower sync in https://github.com/broerse/ember-cli-blog. If I swap out the adapter for a Firebase adapter everything works as expected. (See https://github.com/broerse/ember-cli-blog-fire) It can be some CouchDB setup error on my side but there are no errors in the console. Is there some simple thing I keep overlooking?
Modified the ember-pouch readme to fix this, but to answer here: what you need to do is add
afterModel: function (recordArray) {
// This tells PouchDB to listen for live changes and
// notify Ember Data when a change comes in.
new PouchDB('mydb').changes({
since: 'now',
live: true
}).on('change', function () {
recordArray.update();
});
}

Previous page location on IronRouter

Is there a way to get the previous page location before going to the next page in IronRouter?
Is there an event I can use to fetch this information?
Thanks in advance.
Since Iron Router uses the usual History API, you can just use the plain JS method:
history.go(-1);
or
history.back();
Edit: or to check the previous path without following it:
document.referrer;
You can achieve the behavior you want by using hooks.
// onStop hook is executed whenever we LEAVE a route
Router.onStop(function(){
// register the previous route location in a session variable
Session.set("previousLocationPath",this.location.path);
});
// onBeforeAction is executed before actually going to a new route
Router.onBeforeAction(function(){
// fetch the previous route
var previousLocationPath=Session.get("previousLocationPath");
// if we're coming from the home route, redirect to contact
// this is silly, just an example
if(previousLocationPath=="/"){
this.redirect("contact");
}
// else continue to the regular route we were heading to
this.next();
});
EDIT : this is using iron:router#1.0.0-pre1
Apologies for bumping an old thread but good to keep these things up to date saimeunt's answer above is now deprecated as this.location.path no longer exists in Iron Router so should resemble something like the below:
Router.onStop(function(){
Session.set("previousLocationPath",this.originalUrl || this.url);
});
Or if you have session JSON installed (see Session JSON)
Router.onStop(function(){
Session.setJSON("previousLocationPath",{originalUrl:this.originalUrl, params:{hash:this.params.hash, query:this.params.query}});
});
Only caveats with thisis that first page will always populate url fields (this.url and this.originalUrl there seems to be no difference between them) with full url (http://...) whilst every subsequent page only logs the relative domain i.e. /home without the root url unsure if this is intended behaviour or not from IR but it is currently a helpful way of determining if this was a first page load or not

Meteor: Can't replace document in restricted collection

I am using Meteor 4.2 (Windows) and I am always getting the "update failed: 403 -- Access denied. Can't replace document in restricted collection" when I am trying to update an object in my collection. Strangely I had no problem inserting new ones, only updates are failing.
I tried to "allow" everything on my collection:
Maps.allow({
insert: function () { return true; },
update: function () { return true; },
remove: function () { return true; },
fetch: function () { return true; }
});
But still, this update fails:
Maps.update({
_id: Session.get('current_map')
}, {
name: $('#newMapName').val()
});
Is there something else I can check? Or maybe my code is wrong? Last time I played with my project was with a previous version of Meteor (< 4.0).
Thanks for your help.
PS: Just for information, when I do this update, the local collection is updated, I can see the changes in the UI. Then very quickly it is reverted along with the error message, as the changes has been rejected by the server-side.
Alright, the syntax was actually incorrect. I don't understand really why as it was working well before, but anyway, here is the code that works fine:
Maps.update({
Session.get('current_map')
}, {
$set: {
name: $('#newMapName').val()
}
});
It seems like it must be related to what you're storing in the 'current_map' session variable. If it's a db object, then it probably looks like {_id:<mongo id here>} which would make the update finder work properly.
I ran into the same issues, and found the following to work
Blocks.update {_id:block_id}, {$set: params}
where params is a hash of all the bits i'd like to update and block_id is the mongo object id of the Block i'm trying to update.
Your note about the client side update (which flashes the update and then reverts) is expected behavior. If you check out their docs under the Data and Security section:
Meteor has a cute trick, though. When a client issues a write to the server, it also updates its local cache immediately, without waiting for the server's response. This means the screen will redraw right away. If the server accepted the update — what ought to happen most of the time in a properly behaving client — then the client got a jump on the change and didn't have to wait for the round trip to update its own screen. If the server rejects the change, Meteor patches up the client's cache with the server's result.

Resources