How to pass an object to link-to + queryParams in Ember? - ember.js

I'm currently in a situation that I need to pass one object to {{link-to}}, but queryParams does not accept objects {key:value}. I need this feature because I'm using this component in different templates. The reason for doing that is that one template uses some keywords to use as a filter that the other template does not use and vice-versa.
I started using my own helper to generate the link, but I realize that the anchor my helper was generating was reloading the whole page and link-to does not do that. I'd like to reproduce that behavior, because there are other variables set on the view which I'm using and they all get reset to their default values whenever I reload the page
Is there a smart way to create a link using objects now? I saw some answers but they were all related to ember 1.+ and canary. In all of the answers they were saying it was not possible. I wonder if people have implemented this now or if a solution for this problem is being used currently and I could not find...
Thanks!

So I really could not find a way to do this. What I've done instead was creating {{actions}} inside my anchors and then I used transitionTo() to simulate the behavior of {{link-to}}.
A nice way of doing that can be seen here
Ember transitionToRoute cleanly in a component without sendAction

Related

Template inheritance in Ember

I have several unrelated pages that use Layout A, and another set of unrelated pages that use Layout B. It's as simple as that, but I can't figure out how to do this in Ember the DRY way.
I understand that template nesting is equal to route nesting, but I do not want to nest routes because it'd mean the URL will be also nested. I want to nest templates only because the pages are unrelated.
What I want to achieve is essentially template inheritance.
I expected this to work, but Ember throws an error.
// app/routes/samePage.js
import Ember from 'ember';
export default Ember.Route.extend({
renderTemplate(){
this.render('somePage', {
into: 'layoutA'
});
}
});
This is the error I get:
ember.debug.js:18015 Assertion Failed: You attempted to render into 'layoutA' but it was not found
I also get this warning. It tells me to read this link, but I don't think it helps me.
DEPRECATION: Rendering into a {{render}} helper that resolves to an {{outlet}} is deprecated. [deprecation id: ember-routing.top-level-render-helper] See http://emberjs.com/deprecations/v2.x/#toc_rendering-into-a-render-helper-that-resolves-to-an-outlet for more details.
Here is what layoutA.hbs would look like. I know you can't have {{outlet}} multiple times in a same template, but you probably get what I want to achieve.
<div class="header">
{{outlet}}
</div>
<div class="content">
{{outlet}}
</div>
<div class="footer">
{{outlet}}
</div>
How do I go about doing this in Ember? It sounds like such a basic task that needs to be more clear. Do I need to implement a template inheritance helper (like the one shown here) by myself? Or perhaps, there's already an Ember add-on for that?
Unfortunately, there is no such thing as template inheritance in Ember. But there are two features that allows to reuse html-code:
Components is well-known feature of Ember. It allows to have a re-usable template and/or js code to control such template appearance and behaviour. Component has it's own context, so all data should be passed to it via properties. I recommend to use components for custom ui elements or when you need to reuse a part of template with some logic (for example, top navigation with user menu which depends on authentication can be moved to component). There is also a trick that allows to emulate template inheritance with components using multiple {{yield}}. Maybe that's what you want.
Partials seems to be less known (they are not even mentioned in official guide for 2.x) but very useful. This helper ({{partial}}) renders any template in current context. I recommend to use it when you need to break a big template into parts.
These features are enough to reduce an amount of duplicated code. You probably can't reduce duplicated code to zero with them, but in my opinion it's not critical. Just move what you can to partials/components and your templates will be clear enough. Use that trick with component and yield if you want to emulate inheritance.
Update
Couple of words about partials
If you google "ember component vs partial", you can see a few blog posts and answers on SO, in which ppl say "don't use partials". In many cases without explaining why. The main points that I found are:
Components are more isolated, decoupled and testable. And I agree with that.
Partials may be deprecated and removed in future. However, that was first said in year 2015, but at this moment partials are still there and not deprecated.
When I suggest to use partials?
When you have a big template that is hard to maintain and you can't drop that route in parts. It happens if you use some css-framework (like bootstrap or semantic-ui) and need to implement a couple of big 3-4 step forms, or add a couple of modals or display some complex entity. Using components in this case is unneccessary (you will not use them on any other page) and their isolation adds headache (you will need to pass data that you need to display as properties and add some action(s) to get user input in case of forms).
Why I suggest to use partials in this case?
There is no need to reuse such partial, we just want to break template for easier maintenance. For example, to have each step of 3-steps form in it's own .hbs file rather than having one big template.
If partials will be deprecated, it's easy to move that pieces back to one big template.
It sounds to me like your solution is pretty simply just to use Ember components. Ember components have their own template which can nested into your route's template with {{name_of_component}}, however using components does not affect the routing.
Perhaps I am misunderstanding your need, but it seems to me like this is the easy fix. Read about it here. If I am misunderstanding the question, please clarify!
What I want to achieve is similar to using named outlets, so I can output some content into a specific place. However, it seems like Ember's recommend way to do this is to use ember-elsewhere.
The documentation says:
Before named outlets were introduced to Ember the render helper was used to declare slots for this.render in routes. This usage is not common in modern, idiomatic applications and is deprecated. In general, the pattern of named outlets or named render helpers is discouraged. Instead use of ember-elsewhere or another DOM-redirection library should better serve these use cases.
I found this add-on to be easier to understand over partials and components.
This, or using partials/components is probably the best we can get as Handlebars do not have a template inheritance feature.
Or, I should be changing the way I'm creating the app, and use routes to do template nesting. That's probably the Ember way.

Passing parameters between routes in Ember 2.x

While going from one route to another, I want to pass some data (especcially arrays). How is it possible?
Why can't we use query-params with arrays?
Is it a problem storing data in a specific service during transition?
Note:
I know there are some old questions those are nearly the same with this question. But their selected answers are no more applicable for Ember 2.x. Those questions are: 1, 2.
I´m not sure if queryparams won´t work with arrays as I only used it with single ids, but it would not be a good solutions even if it worked, there´s a limit on how much you can send by parameters and you should not bother any user with your data.
Just create a model to save your data for local use, so you can simply use the ember store
Use a service you´ll have to inject in every controller you want to use your data
I would prefer the model/store variant so you´ll be able to observe and just follow the normal flow which is also good if someone else has to maintain your code.
UPDATED
After testing with "transition.data"; not updating the history seems as a problem for us. So we again use "queryParams". The constraint is: do not pass a complex object between routes
OLD ANSWER
I'm using transition object for this purpose in an action while routing as the following:
let transition = router.transitionTo(route, model);
transition.data[propName] = propValue;
Also I wrote a component to use this code as link-to.

Ember 2.0 Controllers or Just Components...?

I have read that Ember2 is attempting to remove controllers. I was even linked to this RFC https://github.com/ef4/rfcs/blob/routeable-components/active/0000-routeable-components.md. However, I have been following the tutorial, and they insist on making a Controller. Do we still need to make Controllers or is this out of date?
Controllers are still needed (and thus haven't been deprecated) for two reasons: query parameters, and because components aren't routable yet. You can follow the tutorial's use of controllers without it causing you too much grief later on.
However, if you want to pull ahead of the tutorial, you can use components instead, barring the two caveats above. There is no way around using controllers for query parameters, but you can avoid the lack of routable components using this simple hack:
Let's say you're creating a Route called Dashboard. The tutorial will tell you to create corresponding Controller and Template as well. Go ahead and do that, but delete the Controller. Create a component called dashboard-main, move the logic from the Controller to the component.js file and the Template to the component's Template. Then, in the Dashboard Template, just refer to the component:
{{dashboard-main items=model foo=foo bar=bar ...}}
Depending on what you're doing in the Route, you still may need the setupController() method (that's still the only way you can move values other than the model from the route to the template so that they can be passed to the component), and of course your controller/component implementation may have other minor changes, but that's the basic gist of it.
To be most ready for when controllers are deprecated, you should avoid them by using components instead.

Where can I find documentation on Ember's {{control}}?

I don't see a listing in the Ember API. Where can I find which parameters for this template method? Can I use it, given that it's an unfinished feature?
It is not a good idea to use {{control}} yet as it is still being developed and is very likely to change behaviour. Basically it will be like a sandboxed {{render}} which won't inherit any context. It is mentioned on this page of the emberjs guide:
{{control}} works like render, except it uses a new controller instance for every call, instead of reusing the singleton controller.
This helper is currently under heavy development, and will likely change soon.

Why is my {{#each}} not working?

Why is the Ember Snippet i have linked not working? I am setting up a simple ArrayController and fill it with contents upon initialization. Then i want to display the contents of this controller with the help of {{#each}}, but this is not working.
In tutorials i have read through, the following structure is always used:
{{#each AppNamespace.myModelController}}
...
{{each}}
But to make my example work i had to use:
{{#each AppNamespace.myModelController.content}}
...
{{/each}}
Could you have a look at the provided fiddle and tell me what is wrong with it? I assume that i must have done something wrong since i have seen this pattern so often in tutorials.
Note: I am a Javascript beginner coming from Java Server Development. So it maybe easy JS basics that i am struggling with.
I would have posted the complete code here, but the formatting was not working properly.
Link to my JS Fiddle showing my problem
Add a call to this._super() inside your init method.
https://github.com/emberjs/ember.js/pull/1251
Also, not directly related to your question, but it looks like you would benefit from reading #6 here: http://codebrief.com/2012/03/eight-ember-dot-js-gotchas-with-workarounds/
Tried your fiddle with http://cloud.github.com/downloads/emberjs/ember.js/ember-0.9.6.min.js instead of 1.0 pre it is working fine in both the cases.
I'm starting to look at Ember myself and I'm concerned about the process you're using.
As far as I'm aware you shouldn't really be retrieving data directly from the controller like that. The pattern you use should be based upon models, controllers, views and the router.
http://trek.github.com/ is a resource which I have found useful while learning about Ember.
Based upon that example, this would be my take on a small ember test application:
http://jsfiddle.net/zDfBv/
Hopefully that will be of some use to you as a starting point.
If you pass 1 argument to the #each helper it needs to be a Ember.Array compatible object-- in your first example you pass the controller when your data is in the content property.. your second example works because you pass the content property.. and there is nothing wrong with doing it that way if you feel like it.
There is however an alternate syntax for the #each helper which you may see more often, it uses element naming {{#each model in myModelController}} ... {{/each}}. When you do it this way Ember takes care of looking for the content property for you because it's the default rendering context for the view.
Assuming you're using the latest version from Github you'll find it takes care of looking for content in both cases so the point becomes moot once that is released as stable.