I'm creating a simple Ember JS app based loosely on the Beginner's Guide on the website. However, I can't seem to get anything to render on the page. When I check the Ember Inspector my routes are all present and I don't see any errors so it's not immediately clear where the problem is.
Here is the html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Coin</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body>
<script type="text/x-handlebars">
<div>Hello</div>
{{outlet}}
</script>
<script type="text/x-handlebars" id="accounts">
<div>accounts</div>
<div class="col-md-2">
<ul class="nav nav-pills nav-stacked">
{{#each}}
<li>account link {{#link-to 'account' this}}{{name}}{{/link-to}}</li>
{{/each}}
</ul>
</div>
<div class="col-md-10">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" id="account">
<ul>
{{#each}}
<li>{{comment}}</li>
{{/each}}
</ul>
</script>
<script src="js/libs/jquery-1.10.2.js"></script>
<script src="js/libs/handlebars-1.1.2.js"></script>
<script src="js/libs/ember-1.4.0.js"></script>
<script src="js/app.js"></script>
<script src="dist/js/bs-core.min.js"></script>
<script src="dist/js/bs-nav.min.js"></script>
<!-- to activate the test runner, add the "?test" query string parameter -->
<script src="tests/runner.js"></script>
</body>
</html>
And here is my app.js file:
App = Ember.Application.create();
App.Router.map(function() {
this.resource('accounts');
this.resource('transactions', { path: ':accounts_id' });
})
App.AccountsRoute = Ember.Route.extend({
model: function() {
return accounts;
}
})
App.TransactionsRoute = Ember.Route.extend({
model: function() {
return transactions;
}
})
var accounts = [{
id: 1,
name: 'Account 1',
}, {
id: 2,
name: 'Account 2'
}];
var transactions = [{
id: 1,
id_account: 1,
amount: 12,
comment: 'blah'
}, {
id: 2,
id_account: 1,
amount: 5,
comment: 'blah2'
}, {
id: 3,
id_account: 2,
amount: 98,
comment: 'blah4'
}];
The one thing that renders properly on the page is the "Hello" in the application template. Nothing shows in the {{outlet}} when I navigate to #/accounts or any of the other defined routes. And in fact, when I add #/accounts in the url even my "Hello" disappears.
Is there something obvious that I'm overlooking? I'm new to Ember so I'm sure it's something silly but I can't figure out where the problem is from the documentation.
edit: I'm using Ember v1.4.0 linked directly from the website and I have checked "Allow access to file urls" in Ember Inspector.
I made a working version of what you started in this ember jsbin
What I noticed you were doing wrong was by trying to link to a non-existing route with this {{#link-to 'account' this}}. You didn't define the account route that I notice you want to receive a parameter. However I think you want to send the id of the current item in the iteration. So you can simply do that by changing this into {{#link-to 'account' id}}.
So 2 important modifications to get to something working was to add the route and to fix the param of the link-to helper. Then I just assumed that you want to show transactions as well and fixed that as well.
Hope this helps.
Related
I've read lots of other SO questions about Ember.Selects, but nothing near enough to work. I have dropdowns to filter certain fields in my returned data. The actual filtering is another issue, I'm just trying to get the dropdown populated at the moment.
Mine work with static arrays declared on my controller, as per the docs, but what I really want is to have the dropdown populated with unique values from the data so I don't have to maintain an options array.
I think all I need is the way to set the select's content property to a field in the model, but just putting content=field or contentBinding=field has not worked.
Any suggestions or best practices on this would be much appreciated.
Here's a working code snippet:
App = Em.Application.create({
displayName: 'Some.App'
});
App.Person = DS.Model.extend({
name: DS.attr('string')
});
// this is testing data that should come from your backend api
App.Person.FIXTURES = [
{id: 1, name: 'John Oliver' },
{id: 2, name: 'Jon Stewart' },
{id: 3, name: 'Cenk Uygur' }
];
// in real life, you'll be using another type of adapter, likely DS.RESTAdapter
App.ApplicationAdapter = DS.FixtureAdapter.extend();
App.IndexRoute = Em.Route.extend({
model: function(params) {
return this.store.find('person');
}
});
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Le Select" />
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.3.0.js"></script>
<script src="http://builds.emberjs.com/tags/v1.7.0/ember.js"></script>
<script src="http://builds.emberjs.com/beta/ember-data.js"></script>
</head>
<body>
<script type="text/x-handlebars">
<h1>{{unbound App.displayName}}</h1>
<hr />
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<h3>Index</h3>
Le Person: {{view Ember.Select prompt='- Select -' content=controller.model optionValuePath='content.id' optionLabelPath="content.name"}}
</script>
</body>
</html>
content of the select view wants to be an array of strings, or an array of objects.
If you want to be able to control which properties are used as the selection and as the value, an array of objects works best.
{{view Ember.Select
prompt="Select Something"
content=modelProperty
optionLabelPath="content.labelProperty"
optionValuePath="content.valueProperty"
value=boundValue
}}
here is a working example
I am just starting with the bare-bones starter kit, trying to do something very basic.
In my end result app, there will be a list of categories and subcategories that serve as the nav for the app. My solution being an Ember novice, and just to get something working, was to start with the tutorial by Tom Dale and try moving from there. So, I set up a variable to hold some dummy models to use just to get something on the screen.
When I try to run the app, I get the error Uncaught TypeError: Cannot set property 'dataSourceBinding' of undefined
EDIT--
I have tried moving the declaration of the categories variable to the top of the app.js file, but still get the same error.
My question is really two questions:
What am I missing/doing incorrectly?
I realize that ultimately setting up the app with the categories as a model on the index action is probably not the best approach. This list needs to be dynamic as it will be configurable by users. Is there a better way to have this dynamic nav included in the main template?
app.js:
MSSWApp = Ember.Application.create();
MSSWApp.Router.map(function() {
this.resource('categories', function() {
this.resource('category', { path: ':category_id' });
});
});
MSSWApp.IndexRoute = Ember.Route.extend({
model: function() {
return categories;
}
});
var categories = [{
id: 1,
title: "Auto & Mechanical"
}, {
id: 2,
title: "Beauty & Fashion"
}, {
id: 3,
title: "Careers & Education"
}];
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="initial-scale=1.0">
<title>Test Ember Model on Index</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script type="text/x-handlebars">
<h1>Categories</h1>
<ul>
{{#each in model}}
<li>
<h2>
{{#link-to 'category' this}}
{{title}}
{{/link-to}}
</h2>
<ul>
<li>
Sub 1-1
</li>
<li>
Sub 1-2
</li>
<li>
Sub 1-3
</li>
</ul>
</li>
{{/each}}
</ul>
{{outlet}}
</script>
<script src="js/libs/jquery-1.10.2.js"></script>
<script src="js/libs/handlebars-1.1.2.js"></script>
<script src="js/libs/ember-1.5.1.js"></script>
<script src="js/app.js"></script>
<!-- to activate the test runner, add the "?test" query string parameter -->
<script src="tests/runner.js"></script>
</body>
</html>
Turns out that the template needs a name, otherwise Ember assumes that's the application template.
setting up the script tag like this:
<script type="text/x-handlebars" data-template-name="index">
did the trick
I have the following minimal app.
Main container has a link to "Todos". When I click "Todos" link it gets a class active and becomes red by following the according css rule. When I submit #/todos url in my browser it loads the correct template with "Todos" link marked with class active.
The problem appears with the nested object links.
When I follow link to a specific todo it renders a todo template and marks the link red. But when I submit #/todos/1 url in my browser it responds with the correct template with the correct model (it shows the id), but link doesn't have a class active.
So my problem is that by submitting url #/todos/1 in browser the according link doesn't get a class active.
JSBin: http://jsbin.com/vopajaro/1#/todos/2
index.html
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-2.0.0.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-1.0.0.js"></script>
<script src="http://builds.emberjs.com/tags/v1.3.0/ember.js"></script>
<script src="app.js"></script>
<link rel="stylesheet" href="app.css"/>
</head>
<body>
<script type="text/x-handlebars" data-template-name="application">
{{#link-to "todos"}}Todos{{/link-to}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="todos">
{{#each}}
{{#link-to "todo" this}}{{id}}{{/link-to}}
{{/each}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="todo">
{{id}}
</script>
</body>
</html>
app.js
var App = Ember.Application.create();
App.Router.map(function() {
this.resource('todos', function() {
this.resource('todo', { path: ":id" });
});
});
App.TodosRoute = Ember.Route.extend({
model: function() {
return [{id: 1, name: 'todo 1'}, {id: 2, name: 'todo 2'}];
}
});
app.css
a.active {
color: red;
}
I am trying to feed fixture data to both a handlebars template and a nested view. With my current setup, the data reaches my handlebars template just fine, but not the view. I suspect I am missing some basic piece of the ember.js puzzle. Would someone please advise me?
I've asked a question about a setup that is similar but uses ajax instead of fixture data, but have further simplified my setup in the hopes of getting some direction.
Thank you!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/leaflet.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script type="text/x-handlebars">
{{outlet}}
</script>
<script type="text/x-handlebars" id="index">
{{view App.MapView id="map" contentBinding="this"}}
<div id="blog">
<ul>
{{#each}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
</script>
<script src="js/libs/jquery-1.10.2.js"></script>
<script src="js/libs/handlebars-1.1.2.js"></script>
<script src="js/libs/ember-1.5.0.js"></script>
<script src="js/libs/ember-data.js"></script>
<script src="js/libs/leaflet-src.js"></script>
<script src="js/app.js"></script>
</body>
</html>
window.App = Ember.Application.create();
App.ApplicationAdapter = DS.FixtureAdapter.extend();
App.Router.map(function() {
this.resource('index', { path: '/' });
});
App.IndexRoute = Ember.Route.extend({
model: function () {
return this.store.find('storyPrev');
}
});
App.StoryPrev = DS.Model.extend({
title: DS.attr('string')
});
App.StoryPrev.FIXTURES = [
{
id: 1,
title: 'You Better Believe This!',
coordinates: [-73.989321, 40.6778]
},
{
id: 2,
title: 'Holy Crap, Unreal!',
coordinates: [-73.989321, 40.6779]
},
{
id: 3,
title: 'Big Bucks Made E-Z!',
coordinates: [-73.989321, 40.6780]
}
];
App.MapView = Ember.View.extend({
didInsertElement: function () {
var map = L.map('map', {zoomControl: false}).setView([40.685259, -73.977664], 14);
L.tileLayer('http://{s}.tile.cloudmade.com/[redacted key]/[redacted id]/256/{z}/{x}/{y}.png').addTo(map);
L.marker([40.685259, -73.977664]).addTo(map);
console.log(this.get('content'));
//THIS IS WHERE I GET STUCK
}
});
The view is backed by a controller, so you would do this.get('controller') to get the controller which is backed by your collection which if you wanted to get the collection (which isn't necessary since you can iterate the controller) you could do this.get('controller.model').
var controller = this.get('controller');
controller.forEach(function(item){
console.log(item.get('title'));
});
http://emberjs.jsbin.com/OxIDiVU/373/edit
I am modelling an administrative interface that helps manage database tables. There are two models: [DbxTables, DbxColumns]. I want to allow the user to choose a table using Boostrap's tab-menu and then be able to see the columns in that table. This mostly works. For instance, if I type http://my.domain.com/index.html#/performance where performance is the name of the table I get the following:
If I decide to go to another table by manipulating the URL -- for instance http://my.domain.com/index.html#/food-- then it will successfully switch to the food columns in the right-hand pane. The problems come in when I use my {{linkTo}} links in the left-hand tab menu. One of two things happens:
If the {{linkTo}} looks like {{linkTo 'columns' this}} then it makes the URL parameter something like <App.DbxTable:ember371:performance> rather than just performance
If the {{linkTo}} looks like {{linkTo 'columns' this.id}} then it sets the ULR parameter correctly (or at least so it appears to in the URL window) but the if I click on "meal" in the left-hand tab menu I get the following error: Object meal has no method 'addArrayObserver'. If I click on something else it follows that error message with "Object meal has no method 'removeArrayObserver' ".
In both of the above cases, after receiving an error, the column names on the right hand side do not update. The first style of {{linkTo}} is what the screencast from Tom Dale seemed to suggest was the right syntax. However, seeing that the links were off I came up with the this.id approach. Any help would be greatly appreciated.
For some additional code context (router.js):
App.Router.map(function() {
this.resource('about');
this.resource('dbx', function() {
this.resource('columns', { path: ':dbx_table'});
});
this.resource('oauth');
this.resource('postTypeMappings');
});
App.DbxRoute = Ember.Route.extend({
model: function() {
return App.DbxTable.find();
}
});
App.ColumnsRoute = Ember.Route.extend({
model: function(table) {
return App.DbxColumn.find(table);
}
});
Model: dbx_table.js
App.DbxTable = DS.Model.extend({
name: DS.attr("string"),
desc: DS.attr("string"),
db_column: DS.attr("string"),
columns: DS.attr("raw")
});
Model: dbx_column.js
App.DbxColumn = DS.Model.extend({
name: DS.attr("string"),
dbType: DS.attr("string"),
insight: DS.attr("string"),
enum: DS.attr("string"),
staticUom: DS.attr("string"),
uomContext: DS.attr("string"),
jsonStruct: DS.attr("string"),
desc: DS.attr("string")
});
Model: store.js
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.RESTAdapter.reopen({
namespace: 'api/lifegadget'
})
});
DS.RESTAdapter.registerTransform('raw', {
deserialize: function(serialized) {
return serialized;
},
serialize: function(deserialized) {
return deserialized;
}
});
UPDATE (adding handlebars):
In order to provide some more detail. Here are the handlebars templates:
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/bootstrap.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<script type="text/x-handlebars">
<div class="navbar">
<div class="navbar-inner">
<a class="brand" href="#">Admin</a>
<ul class="nav">
<li>{{#linkTo "dbx"}}DBX{{/linkTo}}</li>
<li>{{#linkTo "postTypeMappings"}}Post Mappings{{/linkTo}}</li>
<li>{{#linkTo "oauth"}}OAuth{{/linkTo}}</li>
<li>{{#linkTo "about"}}About{{/linkTo}}</li>
</ul>
</div>
</div>
<div id="outlet-target">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" id="about">
<div class='about'>
Admin Screen
</div>
</script>
<script type="text/x-handlebars" id="dbx">
<div class='dbx'>
<div id="dbx-table-pane" class="tabbable tabs-left">
<ul class="nav nav-tabs">
{{#each model}}
<li>
{{#linkTo "columns" this}}{{db_column}}{{/linkTo}}
</li>
{{/each}}
<li id="add-table">
<em>Add DBX Table</em>
</li>
</ul>
<div id="dbx-main" class="tab-content">
{{outlet}}
</div
</div>
</script>
<script type="text/x-handlebars" id="columns">
The columns are:
<ul>
{{#each model}}
<li>{{name}}</li>
{{/each}}
</ul>
</script>
<script src="js/libs/jquery-1.9.1.js"></script>
<script src="js/libs/handlebars-1.0.0-rc.3.js"></script>
<script src="js/libs/ember-1.0.0-rc.2.js"></script>
<script src="js/libs/ember-data-12.js"></script>
<script src="js/app.js"></script>
<script src="js/router.js"></script>
<script src="js/models/store.js"></script>
<script src="js/models/dbx_table.js"></script>
<script src="js/models/dbx_column.js"></script>
</body>
</html>
UPDATE 2:
I've now added a short video that demonstrates the problem: https://vimeo.com/63388787
This looks similar to this question: How to show the string value of a non id field for a model in an ember.js route?
I think you will need to use the serialize hook in your ColumnsRoute to define how the model is turned into the URL dynamic segment.
App.ColumnsRoute = Ember.Route.extend({
model: function(table) {
return App.DbxColumn.find(table);
},
//dbx_table matches the dynamic route name in your router, and I am assuming
// you want to use the DbxColumn.name as the URL parameter
serialize: function(model) {
return {dbx_table: model.get('name')};
}
});
The model hook handles turning a URL into a model object when the URL is directly navigated to, and the serialize hook is used to construct the URL when a route is transitioned to using an already existing object, such as when transitionTo or a {{#linkTo}} is used.