Closed evolross closed 7 years ago
@evolross can you tell me what version of iron router you are using?
These are the package versions:
iron:controller@1.0.8
iron:core@1.0.11
iron:dynamic-template@1.0.8
iron:layout@1.0.8
iron:location@1.0.9
iron:middleware-stack@1.1.0
iron:router@1.0.9
iron:url@1.0.11
I looked at these and these haven't changed in my app for months because I've been on the same version of Meteor (1.1.0.3) for a long time. So not sure what happened.
yeah that is very strange. if nothing has changed with anything iron
related, it seems like the problem must be elsewhere, but i'll see what i can come up with. closing this for now
I figured out what the issue is. It may still be a bug. It has to do with me defining a route with this pattern:
this.route('productView', {
path: ['/', '/:productCode'],
waitOn: function() {
if(this.params.productCode) {
return Meteor.subscribe('productByCode', this.params.productCode);
}
else
return Meteor.subscribe('productByCode', '123456789');
}
...
I was trying to define a route who's path could be /
or /:productCode
and if the route was /
it would subscribe to a default product (e.g. 123456789) using the same route logic (including waitOn
, data
, action
, etc.)
Something about this pattern breaks Router.go('productView', {productCode: productCode})
when called from a form. Maybe having a path
with both /
and a param?
If this doesn't ring any bells, I'll make a small reproduction package. It's just odd because whatever it is it breaks in iron_url.js
.
@evolross where did you get the idea that you could provide an array for a path?
ahh, interesting. i never looked under the hood at the iron url parser... looks like you can provide an array to pillarjs/path-to-regexp
i think one issue is that the first parameter in route()
is the path
property, but you're setting it again in object you're passing
when i tried to do this.route(['/', '/:productCode'], {...})
i get Router.route requires a path that is a string or regular expression.
based on https://github.com/iron-meteor/iron-router/blob/devel/lib/router.js#L116, arrays are not valid for the path property... i also found this open issue which discusses this functionality https://github.com/iron-meteor/iron-router/issues/727
It does work though to pass an array to path
. For example I have this route that works great:
this.route('appGateway', {
path: ['/hello', '/hola', '/welcome'],
});
I could break those all out and use Router.go
calls to direct them to where they should go but that's an easy one.
Above, I could break that out as well but that route is about 100 lines of code: it has complex subscriptions, sub-object data queries and loading, complex action, etc. In the spirit of DRY, I don't want to have an extra 100 lines of duplicate code in my router code if possible.
This pattern actually works nicely:
this.route('productView', {
path: ['/', '/:productCode'],
waitOn: function() {
if(!this.params.productCode)
this.params.productCode = '123456789';
return Meteor.subscribe('productByCode', this.params.productCode);
...
You just lose functionality to Router.go('productView', {productCode: productCode})
and you have to use Router.go('/')
or Router.go('/123456789')
instead.
Just curious, does Flow Router handle this any better?
@evolross what you actually have there (and i avoided mentioning this before because it was tangential to the real issue), i believe, is an anti-pattern for several reasons...
think about this for a minute... if you do Router.go('appGateway')
in your example above, which path is the router supposed to use?
here's how routing is supposed to work:
this.route('productView', {
path: '/products/:productCode',
waitOn: function() {
var code = this.params.productCode || '123456789';
return Meteor.subscribe('productByCode', code);
}
})
So given your above route/template with path /products/:productCode
that you can pass any product code to and given also we need the /
path to display that same route/template with a pre-set default product (e.g. 123456789
) but don't want to "redirect/update" the URL. I want it to show default product 123456789
but for the path to remain somedomain.com
(i.e. /
). So no calling Router.redirect
or Router.go
because I won't want the path to update to /products/123456789
.
How is this accomplished without completely duplicating the route code?
that would also be considered and anti-pattern, i would say... there are almost certainly better ways to implement whatever business logic is driving this, but you have more information about it than i, so i digress
i think creating a products
controller would let you accomplish this with minimal duplication
p.s. the anti-patterns are:
product
hence wanting to respect DRY. I just simplified my example.Will look into Route Controllers. And I should probably be using Flow Router or React Router at this point anyway.
the url thing is basically a semantics argument, i guess... do you have a page where you list all the products?
you can move those 100 lines to a controller and have multiple routes that inherit from it
also, rather than duplicate, you could always refactor your logic into functions (or hooks) that both routes could call
flow router has been abandoned and not updated in a year... react router is a good option but totally and radically different from the other two
if you didn't realize before, you can also keep it as one route the way you have it, just by doing what i mentioned originally but removing /products
(assuming this is the only route in the app, otherwise you may have conflicts or issues depending on the load order, etc)
this.route('productView', {
path: '/:productCode',
waitOn: function() {
var code = this.params.productCode || '123456789';
return Meteor.subscribe('productByCode', code);
}
})
My app is on Meteor 1.1.0.3 and probably an older version of
iron:router
. Something that just started happening in my app as of a few days (possibly weeks) ago, calling:Router.go('productView', {productCode: productCode})
Returns the following error:
The route looks like this:
Now, the only way that's working is to make the call like this:
Router.go('/' + productCode);
Just curious if anyone was 1. still using
iron:router
and 2. running into this?