Ember breaks due to Prototype.js - ember.js

I am embedding my Ember App into another environment. Prototype.js is in use there. Due to this, ember breaks.
I have read http://emberjs.com/guides/configuring-ember/disabling-prototype-extensions/
I followed that but unfortunately issue is not resolved.
JS Bin: http://jsbin.com/raqab/2/edit
I am not sure what i am doing wrong here, Can anyone please assist me?

In the same guide, where the effect of disabling prototype extensions is explained for arrays, it is said that
Native arrays will no longer implement the functionality needed to observe them. If you disable prototype extension and attempt to use native arrays with things like a template's {{#each}} helper, Ember.js will have no way to detect changes to the array and the template will not update as the underlying array changes.
Additionally, if you try to set the model of an Ember.ArrayController to a plain native array, it will raise an exception since it no longer implements the Ember.Array interface.
You can manually coerce a native array into an array that implements the required interfaces using the convenience method Ember.A:
Therefore change your model hook as
App.ApplicationRoute=Ember.Route.extend({
model:function(){
return Ember.A(["one","two","three"]);
}
});
and in your template,
<ul>
{{#each model}}
<li>{{this}}</li>
{{/each}}
</ul>
Updated jsbin: http://jsbin.com/hayata/1/edit
Now no error is thrown by ember, but some error is thrown from your other scripts.
Once you fix that it'll be all ok.

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.

Moving an ArrayController/View to a Component in Ember 1.13

I'm currently in the process of updating my Ember App to use 1.13 and am having an issue translating a particular Ember.View and its associated Ember.ArrayController into an Ember.Component, as per the Deprecation Guide.
After repurposing some code, I now have the following:
app/templates/page.hbs
{{example-component content=posts}} // "posts" being an array of objects
app/templates/components/post-list.hbs
{{#each content key="#index" as |post|}}
{{post.title}}
{{/each}}
In some cases, the order of the items in the posts array will need to change (via the Ember.SortableMixin), and these changes need to be reflected on screen. When I do this, however, it seems as though content isn't being binded correctly and doesn't update visually (though the order of the posts data is correct in the PageController).
I hope this makes sense. Any help is greatly appreciated!
With the help of #locks in Freenode IRC, I have an answer. The issue had to do with the key that was being iterated on in the {{#each}} loop. By changing it to key="#identity" (Ember 1.13.2) it now works as desired.

What changed on the {{action}} behavior since RC3.1 that breaks the ember.js todo code

Im currently working through the Ember.js Getting started Guide, but i'm using v1.0.0-rc.6.3 instead of RC3.1 as mentioned in the Guide.
Now i reached the chapter about implementing the editing of single todos, but the {{action}} handler implemented in the Guide dosn't seem to work, so my fist assumption is that the behavior of events changed.
Here is my code so far in a JSBin: http://jsbin.com/ogixej/1/edit
As you can see, when you double click a todo item a error is raised in the console:
Uncaught Error: Nothing handled the event 'editTodo'.
Could you tell me what changed an how i'm supposed to do it in a correct manner?
Since your TodoController is the controller responsible for the items you need to define this on your TodosController, like this:
Todos.TodosController = Ember.ArrayController.extend({
itemController: 'todo',
...
});
This way the editTodo function is correctly invoked. Here your working jsbin.
Hope it helps.
I recognize that this should be a comment, but my reputation is too low, yet.
While #intuitivePixel's answer is correct, and accepted, it did not work for me later in the example, during the Transitioning examples (Getting Started Guide - Adding Child Routes). Once I broke the templates apart, I had to move the itemController property from the controller and into the template, during the {{#each}}, like so:
{{#each itemController="todo"}}
...
{{/each}}
If you look closely, you can find this code in Ember's first example block, but it's not called out in the surrounding narrative, so I missed it.

Updating backed array in Ember.js rc1 does not propogate to view

I am trying to upgrade a partially built UI to the latest Ember.js rc1 and it has turned into a very big rewrite job thanks to the dramatically changed API. Most info out there (and here) has been rendered useless. I've had to go through the documentation again several times to get things partially working but there are a lot of loose ends. Here is a biggie. The views do not update like they did under the previous version. I'm missing something that must have to do with rerender, {{outlet}} or something else that I'm not aware of. The ember guides seem to need updates.
The template is very simple:
<script type="text/x-handlebars" data-template-name="index">
<button {{action "addOne"}}>add one</button>
<ul>
{{#each item in controller}}
<li>{{item.title}}</li>
{{/each}}
</ul>
</script>
When clicked, the button adds a new element to the backed array. The console logs show that the array is growing, but the template does not change. Here is a jsfiddle to illustrate how far I've gotten. Can anyone figure out what needs to be added?
I modified your example to highlight the fact when we use arrays in Ember, that we are using Ember arrays (Ember.A() or Em.A() if you want to make explicit this fact). From my understanding, you can use the methods Em.A().addObject and Em.A().removeObject to achieve the basic functionality using the Ember.Object getter and setter methods, (i.e. .get() & .set()) .
In order be properly observed by the Ember application, it is important to use the Ember getters and setters.
A modified version of your fiddle.

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.