Octane & route templates with sane variable names

Background: I personally can’t stand to see this.model in my route templates (or @model). I’ve overridden setupController in my routes in order to set useful variable names on my route templates for years now and, lacking other options, it has been fine.

Last night I went down a rabbit hole reading various RFC’s (lots of cool stuff coming soon!) and I noticed that @model in route templates got merged and this technique with setupController was mentioned as a downside—specifically that you can’t have @post (for example) in your route template. But you could still use the setupController technique to make this.post accessible in your route templates.

So I carried on in my Octane project and was dismayed to find an exception generated:

router.js:1214 Error while processing route: edit-post Assertion Failed: You attempted to update (generated edit-post controller).post to “[object Object]”, but it is being tracked by a tracking context, such as a template, computed property, or observer. In order to make sure the context updates properly, you must invalidate the property when updating it. You can mark the property as @tracked, or use @ember/object#set to do this.

As far as errors go, it’s very helpful (if not wordy). AFAICT, I’m left with a few sub-optimal choices:

  1. Define a minimal controller, just so I can add @tracked post
  2. Use controller.set('post', model) in the setupController hook (or set(controller, 'post', model) for better future-proofing)
  3. Just use @model in my route template and wonder what’s actually in that variable every time I see the file

It’s kind of a bummer to have to define a controller just to have a decent variable name in my template (#1). It’s a bummer to re-introduce set() in my Octane app, which has (up to this point) done completely without it. And it’s a bummer to use @model in my template when I rely on informative variable names.

I think I’m leaning toward #1 at the moment, but if there’s something else I’m missing here please enlighten me! I’m still new to Octane and learning every day.

3 Likes

I can’t give you a solution, unfortunately, but I wonder how your 1) above would work.

You still have to assign controller.post to controller.model in setupController and even that would only give you this.post in your template (not @post), wouldn’t it?

1 Like

Yes indeed. While @post would be even better, I’m happy enough with this.post. At least I can look at it and know immediately what it is.

I guess that one other way I could approach this is by adopting a convention to always return a hash from the model() hook so I could use @model.post. I frequently find myself returning a hash from the model hook anyway (eg, {post, author}) so this would probably suffice for me.

The other way I’ve dealt with this is by defining controllers and aliasing model (or keys in model if it’s a hash) to make my templates read better. I guess now that I’ve thought some more, I think I prefer aliasing over using setupController. I think the corresponding js file is a more natural place to look for a value than the route.

Anyway I think establishing a convention to always return a hash from the model() hook is the cheapest, most reasonable solution for me. Then I can treat @model like this.args in a component. Problem solved! Thanks for replying and inspiring me to think some more about this. :smiley:

And I suspect that that convention is more in-line with this idea that the model hook will eventually be replaced by an args hook (which is mentioned briefly at the bottom of that rfc as well).

1 Like

Yes, I’m becoming less and less enchanted with setupController. Too bad there’s no nice solution for your problem currently, I like the look of @post in the template. Maybe with (some version of) routable components, it’ll become reality :stuck_out_tongue:

1 Like

Anyway I think establishing a convention to always return a hash from the model() hook is the cheapest, most reasonable solution for me.

I’ve personally always liked using hash for a model so anything referenced in the template is clearly coming from the route model. Sure it’s not as short but it’s very explicit and back when everything was ambiguously scoped it was nice to know what was defined on the controller vs coming from the model.

1 Like