Multiple Adapters Single Store Issue - ember.js

I am trying to use different Adapters for 2 different Ember Models but this setup seems to be having problems. I'm able to fetch(find) the 2 models using their respective adapters but when i try to save(commit) them, an issue arises and both try to use the first model's adapter only.
<html>
<head>
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/ember-latest.js"></script>
<script type="text/javascript" src="js/ember-data-latest.js"></script>
</head>
<body>
<script type="text/x-handlebars" id="application">
<h1>Application</h1>
{{ outlet }}
</script>
<script type="text/x-handlebars" id="index">
<h1>Index</h1>
<b>Create</b>
<a href="#" {{action "createOne"}}>Create One</a>
<a href="#" {{action "createTwo"}}>Create Two</a>
<hr>
<b>Load</b>
<a href="#" {{action "loadOne"}}>Load One</a>
<a href="#" {{action "loadTwo"}}>Load Two</a>
</script>
<script>
App = Ember.Application.create();
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.RESTAdapter.extend({
url: "/one"
})
});
App.Store.registerAdapter("App.Two",DS.RESTAdapter.extend({
url: "/two"
}));
App.One = DS.Model.extend({
name: DS.attr("string",{defaultValue:"one"})
});
App.Two = DS.Model.extend({
name: DS.attr("string",{defaultValue:"two"})
});
App.IndexController = Ember.ObjectController.extend({
createOne: function() {
App.One.createRecord({}).save();
},
createTwo: function() {
App.Two.createRecord({}).save();
},
loadOne: function() {
App.One.find();
},
loadTwo: function() {
App.Two.find();
}
});
</script>
</body>
</html>
The Load One and Load Two links work well and hit the url's GET one/ones and GET two/twos respectively. But On using Create One and Create Two links the links hit are PUT one/ones and PUT one/twos. and not one/ones and two/twos. So Ember is trying to hit the second click of creating two with One's adapter and not changing it to Two's Adapter.
Any idea anyone ?

Related

Ember JS app shows blank page

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.

No 'addArrayObserver' or 'removeArrayObserver'

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.

very Basic ember router example unsolved

I tried this very basic ember router example following the ember-router-example. But when I run it, it shows me an empty page. I checked the console window for any errors, but seems to be fine. Not really sure why this is not working and where am missing.
I am just trying to create the first level links of Home, Sections, items only.
Can somebody help me?
index.html:
<body>
<script src="js/libs/jquery-1.7.1.js"></script>
<script src="js/libs/jquery.lorem.js"></script>
<script src="js/libs/bootstrap.min.js"></script>
<script src="js/libs/handlebars-1.0.0.beta.6.js"></script>
<script src="js/libs/ember.js"></script>
<script src="js/app.js"></script>
<script type="text/x-handlebars" data-template-name="application">
<div>
<ul>
<li><a {{action "doHome"}}>Home</a></li>
<li><a {{action "doSections"}}>Sections</a></li>
<li><a {{action "doItems"}}>Items</a></li>
</ul>
</div>
<div>
{{outlets}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="home">
<h1>yeah right Home</h1>
</script>
<script type="text/x-handlebars" data-template-name="sections">
<h1>Oh v in Sections index</h1>
</script>
<script type="text/x-handlebars" data-template-name="items">
<h1>correct in Items Index Page</h1>
</script>
</body>
app.js :
$(function() {
App = Ember.Application.create()
App.ApplicationController = Ember.Controller.extend();
App.ApplicationView = Ember.View.extend({
templateName:'application'
});
App.HomeController = Ember.Controller.extend();
App.HomeView = Ember.View.extend({
templateName:'home'
});
App.SectionsController = Ember.Controller.extend();
App.SectionsView = Ember.View.extend({
templateName:'sections'
});
App.ItemsController = Ember.Controller.extend();
App.ItemsView = Ember.View.extend({
templateName:'items'
});
App.Route = Ember.Route.extend({
root: Ember.Route.extend({
doHome : function(router,event){
router.transitionTo('home');
},
doSections:function(router,event){
router.transitionTo('sections');
},
doitems:function(router,event){
router.transitionTo('items');
},
home : Ember.Route.extend({
route : '/',
connectOutlets:function(router,event){
router.get('applicationController').connectOutlet('home');
}
}),
sections : Ember.Route.extend({
route : '/sections',
connectOutlets:function(router,event){
router.get('applicationController').connectOutlet('sections');
}
}),
items : Ember.Route.extend({
route : '/items',
connectOutlets:function(router,event){
router.get('applicationController').connectOutlet('items');
}
})
})//root
}) //router
});
I created this fiddle with your code. It seems to be working, just use latest ember and handlebars. And maybe you should change {{outlets}} with {{outlet}}.
EDIT
The above fiddle is not working, see the updated fiddle.
I rewrote the routing code using the new routing API, now it is working as expected.
I believe you are supposed to be using "template" as opposed to templateName when you are defining your templates in your main html file. If you were to create those templates as separate handlebars files and use a build step, you would then use templateName to refer to them (by file name).
Steve

Using multiple named outlets and a wrapper view with no content in Emberjs

I'm trying to use multiple named outlets with Ember.js. Is my approach below correct?
Markup:
<script type="text/x-handlebars" data-template-name="application">
<div id="mainArea">
{{outlet main_area}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="home">
<ul id="sections">
{{outlet sections}}
</ul>
<ul id="categories">
{{outlet categories}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="sections">
{{#each section in controller}}
<li><img {{bindAttr src="section.image"}}></li>
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="categories">
{{#each category in controller}}
<img {{bindAttr src="category.image"}}>
{{/each}}
</script>​
JS Code:
Here I set the content of the various controllers to data grabbed from a server and connect outlets with their corresponding views. Since the HomeController has no content, set its content to an empty object - a hack to get the rid of this error message:
Uncaught Error: assertion failed: Cannot delegate set('categories'
) to the 'content' property of object
proxy : its 'content' is undefined.
App.Router = Ember.Router.extend({
enableLogging: false,
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
connectOutlets: function(router){
router.get('sectionsController').set('content',App.Section.find());
router.get('categoriesController').set('content', App.Category.find());
router.get('applicationController').connectOutlet('main_area', 'home');
router.get('homeController').connectOutlet('home', {});
router.get('homeController').connectOutlet('categories', 'categories');
router.get('homeController').connectOutlet('sections', 'sections');
}
})
})
});
​
If it's any help, I got this error because I was connecting to an Ember.ObjectController instead of Ember.Controller.

ember.js statemanager use for tabs

i have 3 tabs navigation and the content of each tab is different obviously.
i'm thinking about using StateManager in Emberjs to manager my tab views.
http://docs.emberjs.com/#doc=Ember.StateManager&src=false
is that a good idea? or is there a better router out there? i've looked at
sproutcore-routing
ember-routemanager
are those better than the statemanager? what's the reason not to use statemanager?
You can use something along this lines, see http://jsfiddle.net/pangratz666/e3wM7/:
Handlebars:
<script type="text/x-handlebars" >
<ul>
<li {{action "showFirst" target="App.stateManager"}} >First tab</li>
<li {{action "showSecond" target="App.stateManager"}} >Second tab</li>
</ul>
<div class="tab-content" ></div>
</script>
<script type="text/x-handlebars" data-template-name="first" >
first
</script>
<script type="text/x-handlebars" data-template-name="second" >
second
</script>​
JavaScript:
App.stateManager = Ember.StateManager.create({
rootElement: '.tab-content',
initialState: 'firstTab',
showFirst: function(manager) {
manager.goToState('firstTab');
},
showSecond: function(manager) {
manager.goToState('secondTab');
},
firstTab: Ember.ViewState.create({
view: Ember.View.extend({ templateName: 'first' })
}),
secondTab: Ember.ViewState.create({
view: Ember.View.extend({ templateName: 'second' })
})
});​
Also take a look at the blog post Anatomy of an Ember.js App Part I Redux: Routing and Outlets.