Ember json search with multiple TextFields - ember.js

Ember noob here. I'm basically trying to have multiple input fields for multiple parameters. As the user types into the fields, this sends off a request to a PHP script which returns the relevant JSON and displays it.
Ember 1.6.1 (latest version is a pain to learn as all of the docs are
out of date)
Handlebars 1.3.0
jQuery 1.11.1
Here's the code so far (not working for multiple).
index.html
<script type="text/x-handlebars" data-template-name="search">
{{view App.SearchTextField elementId="bedrooms" valueBinding=bedrooms upKeyAction="searchProperties" placeholder="Bedrooms"}}
{{view App.SearchTextField elementId="suburb" valueBinding=suburb upKeyAction="searchProperties" placeholder="Sydney"}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="search/results">
{{#each}}
<h1>{{bedrooms}} - {{street}} {{suburb}}</h1>
{{/each}}
</script>
apps.js
App = Ember.Application.create();
App.Router.map(function() {
this.resource('search', {path: '/'}, function(){
this.route('results', {path: '/search/:suburb/:bedrooms'});
});
});
App.SearchRoute = Ember.Route.extend({
actions: {
searchProperties: function(suburb, bedrooms) {
console.log(suburb);
this.transitionTo('search.results', suburb, bedrooms);
}
}
});
App.SearchResultsRoute = Ember.Route.extend({
model: function(params) {
return Ember.$.getJSON('../test/data.php?suburb='+params.suburb+'&bedrooms='+params.bedrooms);
}
});
App.SearchTextField = Ember.TextField.extend({
keyUp: function (e) {
if (e.target.id == 'bedrooms') {
var bedrooms = e.target.value;
} else if (e.target.id == 'suburb') {
var suburb = e.target.value;
}
console.log(suburb + bedrooms);
this.sendAction('action', suburb, bedrooms);
}
});
After some playing around I got it to work using this (looking more jQuery than Ember, but hey it works)
App = Ember.Application.create();
App.Router.map(function() {
this.resource('search', {path: '/'}, function(){
this.route('results', {path: '/search/:suburb/:bedrooms'});
});
});
App.SearchRoute = Ember.Route.extend({
actions: {
searchProperties: function(data) {
this.transitionTo('search.results', data.suburb, data.bedrooms);
}
}
});
App.SearchResultsRoute = Ember.Route.extend({
model: function(params) {
return Ember.$.getJSON('../test/data.php?suburb='+params.suburb+'&bedrooms='+params.bedrooms);
}
});
App.SearchTextField = Ember.TextField.extend({
keyUp: function (e) {
var data = {suburb:$('#suburb').val(), bedrooms:$('#bedrooms').val()};
this.sendAction('upKeyAction', data);
}
});
Is there a better way to do this?

You are kind of over complicating things IMO,
I'd prefer to observe for the value changes in the controller and act accordingly. Result in much reduced code, and in fact you are actually exploiting the features, the framework provides.
Sample implementation, may need to modify to fulfill your needs
App.SearchController = Ember.ObjectController.extend({
suburb : null,
bedrooms : null,
doSearch : function(){
var model = [{street: this.get('suburb'), bedrooms: this.get('bedrooms')}];
//var model = Ember.$.getJSON('../test/data.php?suburb='+this.get('suburb')+'&bedrooms='+this.get('bedrooms'));
this.transitionToRoute('search.results', model);
}.observes('suburb', 'bedrooms')
});
App.SearchRoute = Ember.Route.extend({
});
App.SearchResultsRoute = Ember.Route.extend({
});
App.SearchTextField = Ember.TextField.extend({});
FIDDLE

Related

content not loading on refreshing blog post - ember.js

I am kind of stuck and can't figure out why the blog post is not reloading on refresh. I know it has to do with the App.PostRoute but can't seem to see what is wrong with it.
App.Router.map(function() {
this.resource('about');
this.resource('posts', function() {
this.resource('post', { path: ':post_id' });
});
});
App.PostsRoute = Ember.Route.extend({
model: function() {
return $.get('/posts').then(function(data) {
return data.posts.map(function(post) {
return post;
});
});
}
});
App.PostRoute = Ember.Route.extend({
model: function(params) {
var posts = this.modelFor('posts');
return posts.findBy('id', params.post_id);
}
});
Tried your js code and it seems to work fine, so i guess it's probably the templates.
http://emberjs.jsbin.com/jivudadewihe/1/edit
hbs
<script type="text/x-handlebars" data-template-name="posts">
<ul>
{{#each post in model}}
<li>
{{#link-to "post" post.id}}
{{post.title}}
{{/link-to}}
</li>
{{/each}}
</ul>
<hr/>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="post">
{{this.id}}<br/>
{{this.title}}
</script>
js
App = Ember.Application.create();
App.Router.map(function() {
this.resource('about');
this.resource('posts', function() {
this.resource('post', { path: ':post_id' });
});
});
App.IndexRoute = Ember.Route.extend({
redirect:function(){
this.transitionTo("posts");
}
});
var postsData = [
{id:"1",title:"post1"},
{id:"2",title:"post2"},
{id:"3",title:"post3"}
];
App.PostsRoute = Ember.Route.extend({
model: function() {
return $.get('').then(function(data) {
return postsData.map(function(post) {
return post;
});
});
}
});
App.PostRoute = Ember.Route.extend({
model: function(params) {
var posts = this.modelFor('posts');
return posts.findBy('id', params.post_id);
}
});

Ember.js: Uncaught TypeError: Cannot read property 'enter' of undefined on transitionTo

I have a fairly simple Ember.js app. Inside a view I call this.transitionTo which gives me the error:
Uncaught TypeError: Cannot read property 'enter' of undefined
The error is in ember.js at line 24596, where currentState is undefined
Here are the relevant parts of my app:
window.Plan = Ember.Application.create({});
Plan.Router = Ember.Router.extend({
location: 'hash'
});
Plan.IndexController = Ember.ObjectController.extend({
});
Plan.Router.map(function() {
this.route('application', { path: '/' })
this.route('index', { path: "/:current_savings/:monthly_deposit/:time_horizon" });
});
Plan.ApplicationRoute = Ember.Route.extend({
redirect: function(){
this.transitionTo('index', 200, 200, 200);
}
})
Plan.IndexRoute = Ember.Route.extend({
model: function(params) {
var result = this.store.find('calculation', params).then(function(data) {
return data.content[0];
});
return result;
}
});
Plan.CurrentSavingsTextField = Ember.TextField.extend({
focusOut: function() {
this.transitionTo('index', 150, 200, 200);
}
});
Plan.MonthlyContributionTextField = Ember.TextField.extend({
focusOut: function() {
this.transitionTo('index', 150, 200, 200);
}
});
Plan.TimeHorizonTextField = Ember.TextField.extend({
focusOut: function() {
this.transitionTo('index', 150, 200, 200);
}
});
Plan.Calculation = DS.Model.extend({
target_goal: DS.attr('number'),
target_return: DS.attr('number'),
expected_return: DS.attr('number'),
downside_probability: DS.attr('number')
});
Plan.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'plan/' + window.targetReturnId
});
HTML:
<script type="text/x-handlebars" data-template-name="index">
<div>
<div>Starting Balance: {{view Plan.CurrentSavingsTextField size="10"}}</div>
<div>Monthly Contribution: {{view Plan.MonthlyContributionTextField size="10"}}</div>
<div>Time Horizon: {{view Plan.TimeHorizonTextField size="10"}}</div>
</div>
<div>
<span>Plan Goal: {{target_goal}}</span>
<span>Required Return: {{target_return}}</span>
<span>Exp Return: {{expected_return}}</span>
<span>Downside Probability: {{downside_probability}}</span>
<span>Time Horizon: {{time_horizon}}</span>
</div>
</script>
This response is:
{
"calculations":[
{
"id":10,
"target_goal":3107800.0,
"target_return":0.089,
"expected_return":0.0708,
"downside_probability":0.0489
}
]
}
The app works as expected until I focus out of the text field, then I get the error.
Ember : 1.5.1
Ember Data : 1.0.0-beta.8.2a68c63a
Handlebars : 1.2.1
jQuery : 1.11.1
Past kingpin2k was totally wrong, I missed the statement about the transition from the view. I apologize.
transitionTo from a component isn't supported (at least from any documentation I could find)
You'll want to send an action out of the component and capture it in your controller or route.
Plan.CurrentSavingsTextField = Ember.TextField.extend({
focusOut: function() {
this.sendAction('go', 199, 200, 201);
}
});
Plan.IndexRoute = Ember.Route.extend({
model: function(params) {
var result = this.store.find('calculation', params);
//if you just wanted the first object
// result.then(function(collection){
// return collection.get('firstObject');
// });
return result;
},
actions:{
go: function(a, b, c){
console.log('transition');
this.transitionTo('index',a,b,c);
}
}
});
http://emberjs.jsbin.com/OxIDiVU/749/edit
This question is quite old but it still seems unanswered as far as my googling has gone. After playing around (Ember 0.13.0) I was able to get the following code to work from inside a component:
this.get('_controller').transitionToRoute('index', 150, 200, 200);
The _ infront of controller does feel like a bit of a hack and that it shouldn't really be accessible to userland code. get('controller') does infact return something completely different.
I do agree navigating from a view (Component) isn't best practice, but for my use case I have a few components that drop in to a dashboard for graphing etc which this is perfect for rather than calling out to controller actions. It helps me keep everything isolated inside a single component.

Ember JS cannot createRecord with new ember-data syntax

I am trying to use the new ember-data syntax like explained here: https://github.com/emberjs/data/blob/master/TRANSITION.md (read from Transaction is Gone: Save Individual Records ).
When I hit the save button I get the error Uncaught TypeError: Cannot call method 'save' of undefined in the console. Also in the network tab, there is no POST request to the api.
The template
<script type="text/x-handlebars" data-template-name="landcode/new">
Code: {{input value=code}}<br />
Image: {{input value=image}}<br />
<button {{action 'saveLandcode'}}>opslaan</button>
The app.js (relevant code)
App.Router.map(function() {
this.resource("landcodes"),
this.resource("landcode", function() {
this.route("new");
});
});
App.LandcodeNewRoute = Ember.Route.extend({
model: function() {
this.store.createRecord('landcode');
},
actions: {
saveLandcode: function(){
this.modelFor('landcode').save(); // does not save
}
}
});
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'api'
});
App.Store = DS.Store.extend({
adapter: 'App.ApplicationAdapter'
});
App.Landcode = DS.Model.extend({
code: DS.attr('string'),
image: DS.attr('string')
});
You are using this.modelFor('landcode') this will take the returned model from App.LandcodeRoute, but your model is returned from LandcodeNewRoute. Just use this.currentModel, since you want the model of the current route.
App.LandcodeNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('landcode');
},
actions: {
saveLandcode: function(){
this.currentModel.save();
}
}
});
Your model for should include the route name as well
App.LandcodeNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('landcode');
},
actions: {
saveLandcode: function(){
this.modelFor('landcode.new').save(); // the correct model
}
}
});

What is the reference for this Ember.js guides setupController multiple models with arraycontroller

Presently I am going though every page and snippit of code in the Ember.js Guides and building a small sample app. Some I have gotten stuck on for a bit but solved. This one however befuddles me.
At http://emberjs.com/guides/controllers/representing-multiple-models-with-arraycontroller/
It's also here but does not use the .get('songs") http://emberjs.com/guides/controllers/representing-a-single-model-with-objectcontroller/
App.SongsRoute = Ember.Route.extend({
setupController: function(controller, playlist) {
controller.set('model', playlist.get('songs'));
}
});
I don't know what playlist.get('songs') is referencing. I assume it's a model object array inner object but I am wrong obviously. But since the example code at their site does not have mock stub data to work from I am just guessing from all of my tests.
The code provided here has some commented out bits to see what I was testing.
<script type="text/x-handlebars" data-template-name="songs">
<h1>Playlist</h1>
<ul>
{{#each}}
<li>{{name}} by {{artist}}</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="playlist">
<h3>Playlist: </h3>
</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0-rc.3/handlebars.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/ember.js/1.0.0-rc.6/ember.min.js"></script>
<script type="text/javascript">
window.App = Ember.Application.create();
App.Router.map(function () {
this.resource('songs');
this.resource('playlist');
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('songs');
}
});
// App.SongsRoute = Ember.Route.extend({
// setupController: function(controller, model) {
// controller.set('model', model);
// },
// model: function () {
// // return songs;
// return playlist.songs;
// }
// });
App.SongsRoute = Ember.Route.extend({
playlist: function() {
var playlist = { songs: [{fish: "fish"}, {fish: "fish"}] };
return playlist;
}.property(),
setupController: function(controller, playlist) {
controller.set('model', playlist.get('songs'));
}
});
App.PlaylistRoute = Ember.Route.extend({
setupController: function(controller, model) {
controller.set('model', model);
},
model: function () {
return playlist;
}
});
App.SongsController = Ember.ArrayController.extend();
var songs = {
duration: 777,
name: 'Ember',
artist: 'Jimmy Smith',
};
var playlist = {
songs: [
{
id: 1,
duration: 777,
name: 'Ember',
artist: 'Jimmy Smith',
},
{
id: 2,
duration: 888,
name: 'jQuery',
artist: 'Hyper Cat',
}
]
};
</script>
Unfortunately this link (http://emberjs.com/guides/controllers/representing-multiple-models-with-arraycontroller/) is a little confusing. They are assuming that a model relationship is there, but they are not showing it.
They are assuming that there is something like this :
App.Playlist = DS.Model.extend({
name : DS.attr('string'),
songs : DS.hasMany('song',{async:true})
});
App.Song = DS.Model.extend({
name : DS.attr('string')
});
And then generally what you'd want to do is to pull the collection from the model in setupController, and then set that as content on a nested controller that has been needed by the main controller.
App.PlaylistRoute = Ember.Route.extend({
setupController : function(controller,model){
this._super(controller,model);
this.controllerFor('songs').set('content',model.get('songs'));
}
});
App.PlaylistController = Ember.ObjectController.extend({
needs : ['songs']
});
And then since you're using ArrayController for the collection, you have built in sorting if you define the sortProperties and sortAscending properties.
App.SongsController = Ember.ArrayController.extend({
sortProperties : ['name'],
sortAscending : true
});
Here's a JSBin showing the general idea, using the FixtureAdapter.
http://jsbin.com/ucanam/1073/edit

Why model is not accessible inside controller while accessible in handlebar template?

I have a model of patient object
App.Router.map (function () {
this.resource('patients');
this.resource('patient', {path: ':patient_id'}, function(){
this.resource('dashboard', function() {
this.route('summary');
});
});
});
App.PatientRoute = Ember.Route.extend({
model: function(params) {
return App.Patient.find(params.patient_id);
},
setupController: function(){
console.log("Menu Items:" + App.PatientMenuItem.find() );
this.controllerFor('patient').set('menuItems', App.PatientMenuItem.find());
}
});
App.DashboardSummaryRoute = Ember.Route.extend({
setupController: function(){
this.controllerFor('dashboard.summary').set('content', this.controllerFor('patient').get('model'));
this.controllerFor('dashboard.summary').getPatient();
}
});
App.DashboardSummaryController = Ember.ObjectController.extend({
getPatient:function(){
console.log(this.content.get_allergies);
}
});
App.PatientController = Ember.ObjectController.extend({
menuItems:[],
});
<script type="text/x-handlebars" data-template-name="dashboard/summary">
Summary{{this.content.get_allergies}}
</script>
In the above I am not able to access the same get_allergies in DashboardSummaryController but I am able to access it in handlebars, Can anyone help me what is the mistake ?
Thanks in advance
I don't know if this alone solves the problem, but always use the get() and set() methods when accessing properties. So i would suggest to try this in your getPatient() method:
App.DashboardSummaryController = Ember.ObjectController.extend({
getPatient:function(){
console.log(this.get("content.get_allergies"));
}
});
Why does the template work? The Handlebars expression you have there is automatically translated into the call, i have suggested for your controller method.