Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

this.paramsFor(routeName) with the routeName of a route not previously visited #13771

Closed
fknoll opened this issue Jun 29, 2016 · 16 comments
Closed

Comments

@fknoll
Copy link

fknoll commented Jun 29, 2016

Using

Ember      : 2.6.1
Ember Data : 2.6.1
jQuery     : 2.2.4

It seems like using this.paramsFor(routeName) with the routeName of a route not previously visited makes my application fail - not immediately, but later on, when I transition to the route.

When starting my application, I want automatically to show a specific route reg directly nested under the application route.

For route reg I have defined two query parameters - queryParam1 and queryParam2.

In the model() method for application route the default values for those two query parameters are found and saved in defaultQueryParam1 and defaultQueryParam2.

To secure that the navigation to route reg is not already requested via the url http://localhost:4200/reg?queryParam1=xxx&queryParam2=yyy, I am testing for the existence of the query parameter values before requesting the default transition to reg.

For that purpose I have defined

redirect() {
    if ( Ember.isEmpty( this.paramsFor('reg').queryParam1 ) &&
         Ember.isEmpty( this.paramsFor('reg').queryParam2) ) {

      this.transitionTo('reg', {
        queryParams: {
                        queryParam1: this.get('defaultQueryParam1'),
                        queryParam2: this.get('defaultQueryParam2')
                      }
      });

    } // end-if
  },

When using the url http://localhost:4200/reg?queryParam1=xxx&queryParam2=yyy, everything seems to work nice and smoothly.

However, when I use the default start application url http://localhost:4200/ I get this two fatal errors:

ember.debug.js:27773
Error while processing route: regSummary.index delegate is not a function TypeError: delegate is not a function
    at Class._qpChanged (http://localhost:4200/assets/vendor.js:33405:7)
    at Object.apply (http://localhost:4200/assets/vendor.js:32605:18)
    at Object.sendEvent (http://localhost:4200/assets/vendor.js:26069:28)
    at notifyObservers (http://localhost:4200/assets/vendor.js:29972:25)
    at propertyDidChange (http://localhost:4200/assets/vendor.js:29799:5)
    at Object.notify (http://localhost:4200/assets/vendor.js:23823:9)
    at chainsDidChange (http://localhost:4200/assets/vendor.js:29888:9)
    at Object.propertyDidChange (http://localhost:4200/assets/vendor.js:29798:5)
    at Object.set (http://localhost:4200/assets/vendor.js:30199:38)
    at http://localhost:4200/assets/vendor.js:36057:37logError @ ember.debug.js:27773
ember.debug.js:31387
TypeError: delegate is not a function
    at Class._qpChanged (ember.debug.js:23279)
    at Object.apply (ember.debug.js:22479)
    at Object.sendEvent (ember.debug.js:15943)
    at notifyObservers (ember.debug.js:19846)
    at propertyDidChange (ember.debug.js:19673)
    at Object.notify (ember.debug.js:13697)
    at chainsDidChange (ember.debug.js:19762)
    at Object.propertyDidChange (ember.debug.js:19672)
    at Object.set (ember.debug.js:20073)
    at ember.debug.js:25931
@Serabe
Copy link
Member

Serabe commented Jun 30, 2016

Can you please try to replicate the bug in a Twiddle, please. Thank you!

@fknoll
Copy link
Author

fknoll commented Jul 8, 2016

Hallo @Serabe,

See first part of a twiddle reproduction here .

Try URL: /character?firstName=Snif
Unfortunately twiddle does not display the error, that I see in Console on my own PC:

TypeError: Cannot read property 'name' of undefined
    at Class.finalizeQueryParamChange (ember.debug.js:25494)
    at Object.triggerEvent (ember.debug.js:27775)
    at Object.trigger (ember.debug.js:51084)
    at finalizeQueryParamChange (ember.debug.js:50214)
    at Object.queryParamsTransition (ember.debug.js:49592)
    at Object.getTransitionByIntent (ember.debug.js:49505)
    at Object.transitionByIntent (ember.debug.js:49610)
    at doTransition (ember.debug.js:50182)
    at Object.transitionTo (ember.debug.js:49679)
    at Class._doTransition (ember.debug.js:27486)onerrorDefault @ ember.debug.js:31344trigger @ ember.debug.js:52087(anonymous function) @ ember.debug.js:53338invoke @ ember.debug.js:333flush @ ember.debug.js:397flush @ ember.debug.js:205end @ ember.debug.js:560run @ ember.debug.js:682join @ ember.debug.js:702run.join @ ember.debug.js:20313(anonymous function) @ ember.debug.js:20376fire @ jquery.js:3187fireWith @ jquery.js:3317ready @ jquery.js:3536completed @ jquery.js:3552

Any proposals about how to avoid the transition in app/routes/application.js method redirect(), when the application is started with an URL including a route?

  redirect() {

    // Avoid transition when application is started via URL link
    // including target route "character" and query parameter, fx.
    // http://localhost:4200/character?firstName=Snif
    // But, how?

    if ( this.modelFor('application').length > 0 ) {

      this.transitionTo('character', {
        queryParams:  {
                        firstName: this.modelFor('application').get('firstObject').get('firstName')
                      }
      });

    }

  } // end-redirect()

@pixelhandler
Copy link
Contributor

@fknoll is the character route the default route? could use this.route('character', {path: '/'}); to make it so.

@Serabe
Copy link
Member

Serabe commented Jul 15, 2016

Hello, @fknoll:

I cannot see any paramsFor in your Twiddle. Can you please provide the twiddle with the paramsFor problem? It looks like the problem in your second comment is different that the one in the original post. If you cannot get to reproduce it in a twiddle but you can reproduce it in a small project, please, upload it to GitHub and I'll take a look there.

Thank you!

@pixelhandler
Copy link
Contributor

@fknoll have you reached out in the #-help channel of the embercommunity.slack.com chatroom? I'm curious if this may be more of a support need than an Ember bug.

@fknoll
Copy link
Author

fknoll commented Jul 18, 2016

Just returned from a short vacation - I apologize for lack of responsiveness.

I insist on my initial finding: using this.paramsFor(<routeName>) makes Ember fail - not immediately, but later on, when doing a transition to <routeName>.

I have created this reproducible scenario on Ember Twiddle:
https://ember-twiddle.com/c73b62574ff88d64d07bd58e61140001?openFiles=routes.application.js

Look for this code in routes/application.js:

    // If the LET statement below is commented out,
    // then this twiddle example works fine!
    let requestedQueryParam = this.paramsFor('character').firstName;

@fknoll
Copy link
Author

fknoll commented Jul 18, 2016

@pixelhandler Thank you so much for your input - it is appreciated. I understand your proposal! Yes, it might be a simple and usable workaround just to avoid my default transition in routes/application.js. But I have a default transition including query parameters, and I do not know how to handle that scenario by setting this.route('character', {path: '/'}).

@pixelhandler
Copy link
Contributor

pixelhandler commented Jul 22, 2016

@fknoll can the character controller just set a value for firstName: null e.g. in setupController of route or in the code? (i.e. change null to 'something') ?

this.paramsFor(routeName) with the routeName of a route not previously visited

I'm curious, perhaps I should not expect to have the 'params' available from a controller that was "not previously visited". Looking up the params in the application route for the params for a controller in a child route that has not been visited yet seems like an issue on the subject of "putting the cart before the horse". Which is why I suspect that there is perhaps a different implementation for your use case.

In the model() method for application route the default values for those two query parameters are found and saved in defaultQueryParam1 and defaultQueryParam2.

What about using the setupController hook in the child route to lookup saved properties on the application route and set them on the controller now that it's ready?

dguettler added a commit to dguettler/ember.js that referenced this issue Jul 31, 2016
@dguettler
Copy link

dguettler commented Aug 5, 2016

Anybody willing to take a look at the test for this? The code change fixes the issue in above twiddle example.
The test would need to call paramsFor before the _qpDelegate method is called so a _qpChange is triggered before _qpDelegate is assigned

@pixelhandler
Copy link
Contributor

@fknoll we discussed this issue a bit an the bottom line is… if a route hasn't been visited, it doesn't have paramsFor.

@pixelhandler
Copy link
Contributor

pixelhandler commented Aug 5, 2016

The docs need clarity, see http://emberjs.com/api/classes/Ember.Route.html#method_paramsFor

This issue is more of a documentation issue Route#paramsFor needs to be used in a timely fashion. The route instance has a lifecycle and the model hook receives the params. paramsFor can't expect that any route in the app has a value for it's params, or that any route in the app has been instantiated. Ideally it should be used in a route, looking up it's own params after the model hook is fired, or looking up params from a parent route since that route has been setup already.

Serabe added a commit to Serabe/ember.js that referenced this issue Aug 5, 2016
Improve documentation on `Route.paramsFor`.

Fixes emberjs#13771
@fknoll
Copy link
Author

fknoll commented Aug 6, 2016

@Serabe @pixelhandler @dguettler

Thank you to all of you for investigating into this problem of mine.

@pixelhandler, I do understand your position. Nevertheless, I find it unacceptable that an Ember application stops working after using paramsForon a route not previously visited.

Besides, I am still challenged by my original quest: At default start-up (e.g. http://localhost:4200/my-app), I want my application automatically to navigate to a n-level deep route - including two at start-up calculated query parameters (the current date, and the employee id of the user logged in). But, if the user has started my application via a none default URL (e.g. http://localhost:4200/my-app/level1/level2/level3/?employeeId=3&regDate=2016-08-06) , I certainly do not want the default navigation to be executed.

Thus, I am looking for a way to detect, that I am not dealing with a default start-up, but instead by a start-up initiated by specific none default URL request.

@Serabe Serabe added the Has PR label Aug 6, 2016
@Serabe
Copy link
Member

Serabe commented Aug 6, 2016

Hello, @fknoll:

We took some time to get to know how Ember.Route.paramsFor should work and realise that this was a problem in the documentation: a route can only access the params for an ancestor route, pretty much like modelFor works.

The documentation problem is being addressed in #14034.

If I had to redirect all the users getting to my app at the root level (let's say /), but not if my user gets to a different route (like /non/root/path), then I would use the index route. You can find more information about index routes in general in the guides. In general, I find the routing section of the guides to be a pretty good guide to the Ember routing system.

Please, for questions on how to use the framework for your specific needs, use the -help channel in Slack, discourse or StackOverflow.

Thank you!

@fknoll
Copy link
Author

fknoll commented Aug 6, 2016

@Serabe - Thank you :-)

@fknoll fknoll closed this as completed Aug 6, 2016
@Serabe
Copy link
Member

Serabe commented Aug 6, 2016

Reopening this to track the documentation issue.

@Serabe Serabe reopened this Aug 6, 2016
toddjordan pushed a commit to toddjordan/ember.js that referenced this issue Sep 9, 2016
Improve documentation on `Route.paramsFor`.

Fixes emberjs#13771
webark pushed a commit to webark/ember.js that referenced this issue Oct 6, 2016
Improve documentation on `Route.paramsFor`.

Fixes emberjs#13771
rauhryan added a commit to huboard/huboard-web that referenced this issue Oct 6, 2016
rauhryan added a commit to huboard/huboard-web that referenced this issue Nov 14, 2016
@mangatinanda
Copy link

mangatinanda commented Dec 21, 2016

@Serabe @pixelhandler I have an use case where I am setting queryParams of route which is not visited yet and then visiting the route(after some action has happened), which crashes the app.
I see TypeError: delegate is not a function in the console.

The below code in the beforeModel hook of the route fixes this:

// controller for the list route for which query params are set before visiting the route
beforeModel() {
  let controller = this.controllerFor('list');  
  controller._qpDelegate = this.get('_qp').states.allowOverrides;
}

I know I am not supposed to change the private methods of controller, but I am unable to understand why this error is occurring.

Someone please shed some light on this. Related to #11592
@trek @stefanpenner @rlivsey

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants