I'm going over Ember - Getting Started tutorial but I got stuck. Everything was fine until I got to Displaying-Model-Data section:
First, adding:
Todos.TodosRoute = Ember.Route.extend({
model: function () {
return Todos.Todo.find();
}
});
to the router.js file results in blank window, I found this post which helped returning the layout by adding the next line of code before the code above:
Todo.TodosController = Em.ArrayController.extend({});
Second, as I continue one step forward and try to replace the static index.html with handlebars to make it dynamic (by this code):
<ul id="todo-list">
{{#each controller}}
<li>
<input type="checkbox" class="toggle">
<label>{{title}}</label><button class="destroy"></button>
</li>
{{/each}}
</ul>
again my layout disappears and leaving me with a blank window.
I follow this tutorial step-by-step so don't know what could cause that.
(Found other relevant post but nothing was helpful).
After a few debug time, I found out what was the problem, but not exactly sure why.
I used handlebars.js (V 1.0.0) as published in the official site handlebarsjs.com (this is the one which also linked by the Ember Getting started guide in the dependencies section). After replacing it with the one in cloudflare the layout was brought back to life.
Hope it will help someone.
p.s: after this change the addition of
Todo.TodosController = Em.ArrayController.extend({});
is no longer relevant.
Related
In an Ember application (Ember v3.13) I tried to iterate through an array of audio URLs, using an each loop in a template, and generate an audio tag for each...
I get the following error:
Assertion Failed: fullName must be a proper full name
The audio tag works fine outside of the each loop.
Wondering if anybody has seen this before or know what it means or if there’s a workaround?
This is the code in question:
{{#each audioURLS as |audio|}}
<li>
<audio controls preload="none" src={{audio}}>Your browser does not support the audio element.</audio>
</li>
{{/each}}
Try using a different variable name. The introduction of angle bracket component invocation has caused problems with code that tries to invoke a component while passing in a variable with the same name:
{{#each audioURLS as |src|}}
<li>
<audio controls preload="none" src={{src}}>Your browser does not support the audio element.</audio>
</li>
{{/each}}
I see what the problem was now. It was mentioned in this issue:
https://github.com/emberjs/ember.js/issues/17219
I had audio as the block param and was then trying to invoke the HTML5 audio tag and it caused a collision.
It’s a shame the error message was so completely vague, it often seems to be the case with Ember.
Updated my code from this:
{{#each audioURLS as |audio|}}
<li>
<audio controls preload="none" src={{audio}}>Your browser does not support the audio element.</audio>
</li>
{{/each}}
to this:
{{#each audioURLS as |a|}}
<li>
<audio controls preload="none" src={{a}}>Your browser does not support the audio element.</audio>
</li>
{{/each}}
And then it worked just fine.
Given my current router:
Posts
Create
Post
Edit
Comments
Create
Comment
InnerComments
Create
InnerComment
Index (post.comment.innerComment.index)
Ember.js is not loading any existing innerComments from the backend, but it is doing a hell of a job in creating and saving them like the picture below:
Not only I am able to create the inner comments, I am also able to successfully edit them as long as I do not reload the page... This unique behaviour tells me that the issue seems to be rather specific, but I just cannot find it. The code snippets below summarizes how things are loaded in order, but you can also check out the Source Code and these two screenshots with Ember Inspector:
Screenshot 1 - Created Inner Comment
Screenshot 2 - Page Refresh.
Post.Index (model is a post)
{{render "post.comments.index" model}}
Post.Comments.Index (model is a post)
<ol>
{{#each model.comments as |comment|}}
<li>{{render "post.comment.index" comment}}</li>
{{/each}}
</ol>
Post.Comment.Index (model is a comment)
<!--Comment Text, Comment by x User, edit, etc-->
{{render "post.comment.innerComments.index" model}}
Post.Comment.InnerComments.Index (model is a comment)
<ol>
{{#each model.inner_comments as |comment|}}
<li>{{render "post.comment.innerComment.index" comment}}</li>
{{/each}}
</ol>
Post.Comment.InnerComments.Index (model is an innerComment)
<!--InnerComment Text, InnerComment by x User, edit, etc-->
{{model.text}}
One missing line on Serialization has_many :inner_comments was the culprit as it was lost between merging two local branches.
If you have a similar problem, check the developer tools for the network transactions. If one of your XHR requests is missing the expected return payload (the inner_comments for each comment request in my case), then the problem is on your backend...
I have been trying to wrap my head around how Ember routing works on a very basic level and need a little kick in the right direction. I am providing the code I have written so far, hopefully you can follow along and see what is going on
I would like to see a page hierarchy like so:
index
--Red
----Light
----Medium
----Dark
--Green
----Light
----Medium
----Dark
--Blue
----Light
----Medium
----Dark
The "medium" colors are actually going to be the index for each nested route, So I think I need router.js set up like so:
Colors.Router.map(function(){
this.resource('red', { path: '/red' }, function(){
this.route('light-red');
this.route('dark-red');
});
this.resource('green', { path: '/green'}, function(){
this.route('light-green');
this.route('dark-green');
});
this.resource('blue', { path: '/blue'}, function(){
this.route('light-blue');
this.route('dark-blue');
});
});
For now, I just want to serve up static html templates (with just a little bit of #link-to handlebars for navigation)... just so I can see a working prototype.
The main template is here
<div id="emberColors">
<header id="mainHeader">
<h1>Ember Colors</h1>
<p>Pick a color</p>
<nav class="navi main">
<ul>
<li>{{#link-to "red" activeClass="active"}}Red{{/link-to}}</li>
<li>{{#link-to "blue" activeClass="active"}}Blue{{/link-to}}</li>
<li>{{#link-to "green" activeClass="active"}}Green{{/link-to}}</li>
</ul>
</nav>
</header>
{{outlet}}
<footer id="footer">
<p>Ok Buh-bye</p>
</footer>
I have a template for each of the three colors, each is set up like this:
<section id="blue">
<header>
<h1>The Blue</h1>
<p>Blue is cool.</p>
<nav class="navi sub">
<ul>
<li>{{#link-to "blue.light-blue"}}Light{{/link-to}}</li>
<li>{{#link-to "blue"}}Base{{/link-to}}</li>
<li>{{#link-to "blue.dark-blue}}Dark{{/link-to}}</li>
</ul>
</nav>
</header>
{{outlet}}
</section>
And I broke up each "shade" into multiple templates
<div class="color-lt">
<p>Light Blue</p>
</div>
Note: I also understand that I can reuse templates and load different model data into them, rather than hard coding lots of little templates... but I am just trying to focus on learning the routing at the moment.
Because these are just basic templates, I assume (based on what I have read) Ember auto-generates a lot of the MVC and I don't need to define any specific controllers, models, or routes (except for perhaps the IndexRoutes for the three main color landing pages).
I understand that the naming convention for the templates will help ember do most of the work.
However it is the naming conventions that are confusing me.
in router.js it seems simple enough to define the routes by how I want it to appear in the URL
in handlebars {{#link-to}} though, it looks like I need to reference the URL (or template?) name with a . separation (include dashes or no)?
and when defining an index route it is structured with PascalCase?
I need some help with figuring out how to properly name/declare these routes so that Ember can render them correctly.
for instance: because of the nested nature of these pages... do I need to store my templates in a nested directory file structure as well? or is that being done artificially by ember routing?
Is there a general MVC Routing methodology that I am supposed to understand before I can understand Ember Routing specifically?
Sorry, I have a lot of questions about this... It seems like it is supposed to be really simple, but I don't know why I am not getting it. Any help will be greatly appreciated.
EDIT: I will also let you know that, as I have it written out currently, Ember Inspector is not throwing any errors that I can see. So I am convinced, that so far I am on the right track, but I am just not providing anything for the router to resolve...
My Ember.js app is set up roughly like this:
Router:
App.Router.map ->
#resource('site', { path: '/' }, ->
#resource('dashboard')
#resource('account')
#resource('pages', { path: '/:page_slug'}))
Routes:
App.ApplicationRoute = Ember.Route.extend
model: ->
return App.Site.find(1)
App.PagesRoute = Ember.Route.extend
model: (params)->
return App.Page.find(params.page_slug)
EDIT:
Controller (JS not Coffee):
App.PagesController = Ember.ObjectController.extend({
needs: 'ApplicationController',
...
});
I have an ApplicationController and a PagesController. When I'm on a page, I want to call an action to delete the current page. If I place it in the PagesController it works kind of ok, but a navigation menu with a list of pages in the ApplicationView doesn't get updated until I refresh the page. So... I assume I need to place the action in the ApplicationController and add needs: ['ApplicationController'] to my PagesController.
However, when I do that, everything in my Pages template disappears.
I have an {{outlet}} in my Application template and another on in the Site template which ultimately displays the Pages template. Yeah, complicated, I know and there's probably a better way to do it, so any suggestions would be greatly appreciated. Oh and BTW, I'm a real Ember.js newb, so examples need to be spelled out explicitly. (Drawing them with pretty colors in crayon would actually be ideal.)
Thanks in advance for any help.
Here's the refresh issue. In the root resource site I'm loading in one Site model which the Rails backend returns using the url being sent in. Eventually, this app will be used with multiple domains, and each domain will be served it's own website (roughly based on the WP-Multisite concept). Then in the pages route, I'm loading one page of the site based on its slug attribute. That's all working fine. So, now I want to allow the user to be able to add and remove pages as they want.
So, the issue is this. When I delete a page at the PagesController level, the page deletes just fine, but the ApplicationController doesn't get notified. Namely, my nav menu:
<ul class="left">
{{#each page in page}}
<li>{{#link-to 'pages' page.slug}}{{page.menu_name}}{{/link-to}}</li>
{{/each}}
<li id="add-page-button"><a data-tooltip title="Click here to add a new page to your site." href="#" data-reveal-id="addPageModal" data-reveal>+</a></li>
</ul>
doesn't get notified that a page is missing and so it doesn't update the nav menu by removing that page from the list. Adding works fine, the nav list is updated when a new page is added, but I'm doing that at the ApplicationController level like so:
addNewPage: ->
# Get the site
site = #get('model')
# Get all the pages associated with the site
pages = site.get('page')
title = this.get('newTitle')
if (!title.trim())
return
slug = this.get('newSlug')
if (!slug.trim())
return
menu_name = this.get('newMenuName')
if (!menu_name.trim())
return
# Create a new page passing in our title, slug and menu_name
pages.create({title: title, slug: slug, menu_name: menu_name})
# Save the pages
pages.save()
if (pages.isError)
console.log(pages.errors)
else
#set('newTitle', '')
#set('newSlug', '')
#set('newMenuName', '')
$('#addPageModal').foundation('reveal', 'close')
And this is my deletePage code on the PagesController (sorry, I've got a mix of JS and CoffeeScript):
deletePage: function (slug) {
var page = this.get('model');
this.get('ApplicationController').deletePage(page);
this.toggleProperty('isEditingTitle');
this.toggleProperty('isShowingDeleteConfirmation');
this.transitionToRoute('site.index');
}
When I try this, Ember rather helpfully lets me know I need to add needs but again, when I do that, my Pages template is blank.
Oh yes, I have even tried setting the target attribute on the button calling the deletePage action.
I realize what I need to do is somehow access the Site model in my PagesController, but how should I go about that.
This post has taken on epic proportions. Sorry about that. Thanks again for any help.
needs doesn't do anything on the route, if you want to access a controller from a route you can just use this.controllerFor('application')
Additionally when using needs in a controller definition it should be like this needs: 'application' or needs: ['foo', 'application']...
Okay, all, I figured it out. For posterity's sake (and others who go looking for this). Here's how to delete an object in a model that has a belongsTo association.
ApplicationController:
deletePage: function () {
# First we find the Site which all pages belongTo
# Just ignore the hard-coded '1' it's something I have to do to get it to work
site = App.Site.find(1);
# Then we get the current model, i.e., the 'page' we're on and about to delete
page = this.get('model');
# Then, we get all 'pages'
pages = site.get('page');
# We remove the object from the page which updates the navigation menu
pages.removeObject(page);
# We delete the record and save the 'pages' model
page.deleteRecord();
pages.save();
}
Pages template:
{{#if isShowingDeleteConfirmation}}
<div class="large-7 large-offset-5">
<label class="inline left">Are you sure? (Can't be undone)</label>
<button {{action 'deletePage'}} class='button tiny alert'>Yes</button>
<button {{action 'cancelDeletePage'}} class='button tiny'>Cancel</button>
</div>
{{else}}
<div class="large-2 right">
<button {{action 'showDeleteConfirmation'}} class='button tiny alert'>Delete Page</button>
</div>
{{/if}}
I can show you the attributes and logic behind the if...else statement if you need me to.
Basically, the user clicks on the 'Delete' button, showing the other buttons 'yes' and 'cancel'. Once 'yes' is clicked, the deletePage action gets called.
I found very little documentation on the deleteRecord method and basically had to piece this all together myself. Perhaps there's a better way and this can be refactored. Just let me know in the comments.
I'm trying out Ember.js for the first time by roughly following the Ember.js guide, but I'm running into the following problem.
Relevant code:
https://gist.github.com/3257657 (for complete rails app, see: https://github.com/basveeling/ember-test)
Context:
I'm running the latest ember-rails build with the 1.0 prerelease ember.js. I'm using ember-data for the post model.
Almost everything works in this app, except that the hrefs created by {{action showPost context="post" href=true}} have an undefined id (#/posts/undefined).
Furthermore, the jQuery event passed to the showPost action doesn't have a context property (it does have a view property).
Am I going at this the wrong way, or have I perhaps stumbled on a bug in the prerelease?
edit: this might be related to Url contains 'undefined' instead of id after navigating back from 'edit' to 'show'
Try change {{action showPost context="post" href=true}} to {{action showPost post href=true}}
The 1.0 prerelease has changed the action helper.
More info: https://github.com/emberjs/ember.js/commit/83b7a61a892e55423cf1e66f606b13435bcab8f0