How to use Ember query parameters with beforeModel and select? - javascript

Demo: http://jsbin.com/zexopa/1/edit?html,js,output
I use the query parameters in my application. And the queryParameters are 'name' and 'category'.
The 'name' parameter is used in the select and the 'category' uses the input, but there is something wrong with the select 'name' if I set it default to null.
If I change the 'name', the 'name' always is undefined in the url.
Route:
App.IndexRoute = Ember.Route.extend({
beforeModel: function() {
this.controllerFor('index').set('products', [1,2,3]);
},
model: function() {
return [{'is_active':false, 'name':'One'}, {'is_active':false, 'name':'Two'}, {'is_active':false, 'name':'Three'}, {'is_active':false, 'name':'Four'},{'is_active':false, 'name':'Five'}];
},
actions: {
queryParamsDidChange: function() {
this.refresh();
}
}
});
Controller:
App.IndexController = Ember.Controller.extend({
queryParams: ['name', 'category'],
name: null,
category: null
});
Template:
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{view "select" content=products value=name prompt="all"}}
{{input type="text" value=category class="form-control"}}
<ul>
{{#each model as |item|}}
<li>{{item.name}}</li>
{{/each}}
</ul>
</script>
Can you help to check what happens to my application?

Query params must be string to be properly binded. Your input works, as the value is String object. In name array you provided Integer. Unfortunately, I have not found any mention about that in docs, but you can see a working demo here: http://jsbin.com/lixili/1/edit?html,js,output
If I can give you some tip about your code:
beforeModel is not a place for setting controller properties, do it in setupController method as in JSBin provided
You did not defined query params in route, but you could and get rid of the queryParamsDidChange
Hope I helped!

Related

how to populate Ember.Select options via computed property based on selected option of another Ember.Select

I'm struggling to get this basic functionality to work in Ember. How can I populate the options of an Ember.Select view via a computed property that's observing another property which is set through another Ember.Select?
Here's what I've done so far:
HTML/HBS:
<script type="text/x-handlebars">
{{view Ember.Select
content=parent
optionValuePath="content.id"
optionLabelPath="content.name"
value=current_parent}}
{{view Ember.Select
content=child
value=current_child}}
</script>
Javascript:
App.ApplicationController = Ember.ArrayController.extend({
content: '', current_parent: null, current_child: null,
parent: function() {
return this.store.find('user');
}.property(),
child: function() {
var current_parent = this.get('current_parent');
if (current_parent) {
this.store.find('user', current_parent).then(function(parent) {
return parent.get('children');
}
}
}.property('current_parent')
});
App.User = DS.Model.extend({
name: DS.attr('string'),
children: DS.attr(),
});
returned JSON from server:
users: [{id: 0, name: 'test', children: ['child1', 'child2']}]
and obviously this is not working. I'd appreciate explaining where I'm going wrong here and what would a viable method be to implement this, please.
I'm using the following libs:
Ember 1.4.0
Ember Data 1.0.0-beta.6
Handlebars 1.3.0
Thanks in advance!
I don't think you need the derived property child. Instead of using the id as the value you can use the model itself (a user) which already has a property for children. This matched the name you're already using current_parent instead of current_parent_id.
{{view Ember.Select
contentBinding=parent
optionLabelPath="content.name"
value=current_parent}}
{{view Ember.Select
contentBinding=current_parent.children
value=current_child}}
On the controller simply remove the child property.
Hope this helps.

How to affect state of ObjectController from its ArrayController in ember.js

I am still trying to understand how to properly structure an ember.js application. So, this may be a systemic issue with the way I am trying to solve this. That being said, I am going to try asking the same question a couple different ways ...
In the code example below, when a record is created, how can I get it to be added to the list with the isEditing property set to true?
Can I access to a specific object controller from its array controller?
Each task has a view state and an edit state. When a new task is created, how can I have it initially appear in the edit state?
App.TasksController = Ember.ArrayController.extend({
actions: {
createTask: function(){
var task = this.store.createRecord('task');
task.save();
}
}
});
App.TaskController = Ember.ObjectController.extend({
isEditing: false,
actions: {
toggleEditing: function(task) {
if(this.isEditing){
task.save();
}
this.set('isEditing', ! this.isEditing );
}
}
});
<script type="text/x-handlebars" data-template-name="tasks">
<ul>
{{#each task in controller}}
{{render "task" task}}
{{/each}}
<li {{action "createTask"}} >
New Task
</li>
</ul>
</script>
<script type="text/x-handlebars" data-template-name="task">
<li {{action "toggleEditing" task on="doubleClick"}} >
{{#if isEditing }}
{{textarea value=title cols="80" rows="6"}}
{{else}}
{{title}}
{{/if}}
</li>
</script>
Set the property on the model.
You don't have to define the property as an attr on the model (which means it won't send it up to the server on save etc), but you can set the property on the model.
Or you can do it based on the currentState of the model. (click go to orders, then add orders)
http://emberjs.jsbin.com/AvOYIwE/4/edit
App.OrderController = Em.ObjectController.extend({
_editing: false,
editing: function(){
return this.get('_editing') || (this.get('model.currentState.stateName') == 'root.loaded.created.uncommitted');
}.property('model.currentState.stateName', '_editing'),
actions: {
stopEditing: function(){
// blow away the computed property and just set it to true
this.set('editing', false);
},
startEditing: function(){
this.set('editing', true);
},
}
});

Load data from controller in ember.js

I want to implement a system that shows me the newest posts. For this I do not want to use the index action from the user as this is already taken for another post function but a "newest" action. It is showed on the index route with a {{ render "postNewest" }} call. I would prefer to load the data in the PostNewestController or PostNewestView instead of the route for abstraction reasons.
I tried two ideas to achieve this, but none worked so far:
create a custom adapter and add a findNewest() method: the findNewest() method is sadly not found when trying to call in the init method of the controller.
write the request directly into the init method and then update with store.loadMany(payload): data is successful request. However, I do not know how to access the data from the template and set the content of the controller.
Is there any way for this?
EDIT:
Here is the source code to better understand the problem:
PostModel.js
App.Post.reopenClass({
stream: function(items) {
var result = Ember.ArrayProxy.create({ content: [] });
var items = [];
$.getJSON("/api/v1/post/stream?auth_token=" + App.Auth.get("authToken"), function(payload) {
result.set('content', payload.posts);
});
return result;
}
});
PostStreamController.js
App.PostStreamController = Ember.ArrayController.extend({
init: function() {
this.set("content", App.Post.stream());
},
});
index.hbs
{{# if App.Auth.signedIn}}
{{ render "dashboard" }}
{{else}}
{{ render "GuestHeader" }}
{{/if}}
{{ render "postStream" }}
postStream.hbs
{{#each post in model}}
<li>{{#linkTo 'post.show' post data-toggle="tooltip"}}{{post.name}}{{/linkTo}}</li>
{{else}}
Nothing's there!
{{/each}}
PostShowRoute.js
App.PostShowRoute = Ember.Route.extend({
model: function(params) {
return App.Post.find(params.post_id);
},
setupController: function(controller, model) {
controller.set('content', model);
},
});
I Had this issue too. Just add init in your controller, and define the model you want to get there.
In your Controller
App.PostRecentController = Ember.ArrayController.extend({
init: function() {
return this.set('content', App.Post.find({
recent: true
}));
}
});
In your template
{{#each post in content}}
{{post.body}}
{{/each}}
I would recommend you check EMBER EXTENSION, it will give you a good idea of the naming, and see if everything is missing.
I figured out the problem. The Post model has a belongsTo relationship to another model. This relationship is not loaded by Ember so in the stream() method I have to load this manually. Then everything works as expected.

Individual view from an item in an ArrayController

I have an ember.js model and controller setup like so:
//model
App.Order = Ember.Object.extend({
content: null,
create: function(data) {
this.set('content', data);
return this._super();
}
});
//orders controller
App.ordersController = Ember.ArrayController.create({
content: [],
init: function() {
var self = this;
var orders = [];
$.getJSON('js/data.json', function(data) {
data.forEach(function(item) {
var order = App.Order.create(item);
orders.push(order);
});
self.set('content', orders);
});
},
selectItem: function(data) {
alert(data);
}
});
With the following view:
{{#each App.ordersController}}
<div {{action selectItem target="App.ordersController"}}>{{order_number}}</div>
{{/each}}
Which prints out a list of orders with a click action that alerts the corresponding item. This works fine.
What I want to do is show a clicked item in a separate view, eventually with the goal of creating a floating dialogue with orders details shown. I'm new to ember and not sure how this should be implemented. I have a function selectItem which alert's a clicked order but I need to link this to a separate view and print the order details.
Should I store the selected item in a separate controller with a corresponding view and update this when selectItem is clicked? Or could I update a sperate view from the ordersController? Any advice is much appreciated.
When you use the router ember does the instantiation of your class for you. By specifing the "orders" route is looks for a template called orders and a controller called OrdersController if it can't find one it'll generate one for you. (I've omitted the controller for clearity). To load your model from a json source you could have a look at ember-data.
here is a jsfiddle so you can fiddle with it a bit.
You should definitely have a look here these are guides for ember that really help you on the way. The documentation is getting better and better. :)
JS:
window.App = App = Em.Application.create();
//model
App.Order = Ember.Object.extend({
order_number: null,
});
//we create 2 routes one for all the order and one per specific order
App.Router.map(function(){
this.resource('orders', { path: "/" });
this.resource("order", { path: "/:order_id" });
});
//the route supplies the model and handles the event to transition to a new route.
App.OrdersRoute = Em.Route.extend({
events: {
selectItem: function (orderId) {
//select the order by the "orderId" you want as a model for your new view.
this.transitionTo("order", order);
}
},
model: function(){
return content; //an array containing the orders;
}
});
//supplies the model for the "order" route by selecting one acording to the params;
App.OrderRoute = Em.Route.extend({
model: function(params){
return order; //select an object from the array according to the params
},
});
HBS:
<script type="text/x-handlebars" data-template-name="orders">
{{#each controller}}
<!-- this calls the event handler "selectItem" on the ordersroute -->
<div {{action "selectItem" order_number}}>{{order_number}}</div>
{{/each}}
<!-- this is handled by "App.OrderRoute" -->
<a href="#/3"/>with a direct link</a>
</script>
<script type="text/x-handlebars" data-template-name="order">
{{content.order_number}}
{{#linkTo "orders"}}Back to orders{{/linkTo}}
</script>

EmberJS is not automatically showing attributes from context object in view

After following the "Outlets" guide on Emberjs.com (http://emberjs.com/guides/outlets/) I am unable to show the title and body of the post in the Post (child/singular) template. Have any of you run into this? Here's the rundown:
# PostsTemplate
{{#each post in controller}}
<h1><a {{action showPost post href=true}}>{{post.title}}</a></h1>
<div>{{post.body}}</div> <------ title and body show up correctly here
{{/each}}
# PostTemplate
<h1>{{title}}</h1> <---- but title and body are EMPTY here
<div class="body">
{{body}}
</div>
{{outlet}}
# Router
App.Router = Ember.Router.extend({
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
redirectsTo: 'posts'
}),
posts: Ember.Route.extend({
route: '/posts',
showPost: Ember.Route.transitionTo('post'),
connectOutlets: function(router) {
router.get('applicationController').connectOutlet('posts', App.Post.find());
}
}),
post: Ember.Route.extend({
route: '/posts/:post_id',
connectOutlets: function(router, post) {
console.log(post); <------------------ This tells me the post has the write attributes.
router.get('applicationController').connectOutlet('post', post); #This post does not show up in PostTemplate above!
}
})
});
When I run console.log(post), and inspect the post, I see that I have something like the following:
Class = {
id: "1",
_data:
{
attributes:
{
body: "a",
title: "a"
}
},
title: null,
body: null
}
Anyone have any ideas as to why I'm not seeing the title or body attributes show up in the view?
p.s. the Post model is an Ember data model that correctly retrieves the Post with id 1 from a Rails application.
I believe you can use {{content.title}} and {{content.body}} since your Post model should be set to the content of the postController. An easy way to debug this within the view is to put {{content}} in the view which will render the type of model that the item is (such as App.Post).

Categories

Resources