Ember Data: Proper Way to Use findAll - ember.js

I am trying to use ember-data using https://github.com/emberjs/data as a reference.
Specifically, I am trying to use an array controller to display all of the 'Person' objects in my database. I also want to allow the user to create a new 'Person'.
I have the following code which works:
App.peopleController = Em.ArrayController.create
content: App.store.findAll(App.Person)
newPerson: (name) ->
App.store.create App.Person,
name: name
#set('content', App.store.findAll(App.Annotation))
However, it seems inefficient to reset the content property every time a new person is created. If I remove the last line and change the code to the following:
App.peopleController = Em.ArrayController.create
content: App.store.findAll(App.Person)
newPerson: (name) ->
App.store.create App.Person,
name: name
A new view is still created on ever newPerson call, but the same object is duplicated. Essentially what is happening is all of the new templates use the first object created instead of a new one each time. I think this is related to the following bug: https://github.com/emberjs/data/issues/11.
For reference, my template logic is as follows:
{{#each App.peopleController}}
{{#view App.PersonView contentBinding="this"}}
{{#with content}}
Client id is {{clientId}}
{{/with}}
{{/view}}
{{/each}}
When I use the second version of my code-- the one with the #set('content', App.store.findAll(App.Annotation)) line-- the clientId is duplicated for every Person object. In the first version, the client ids are correct.
Can anyone shed some light here? Am I doing this correctly? My instincts are telling me this is a bug but I am not sure.

I think it is a bug. I posted a related issue that illustrates this issue.

Try using the #collection view instead.
See code of ToDo example. Also see http://guides.sproutcore20.com/using_handlebars.html section 5 for some documentation.
Hope this helps.

Related

Emberjs 1.8 handlebars "view select" set default value/prompt text with variable

I want to set a default value or prompt a text to my select dropdown, I have managed to get the correct content into the select, but I want to be able to have a default value that differs from the content, for example " select country " and then list the countries.
This is how the select looks like so far, and the testing variable looks like this: testFillSelect: "Select Country..",
<div class="form-group">
<label>Countries:</label>
{{view "select2"
prompt="Select country.."
content=countries
optionValuePath="content.id"
optionLabelPath="content.name"
selectionBinding=testFillSelect
selection=countries.id
class="form-control"}}
</div>
The problem is, the selectionBinding doesn't seem to work as it does nothing, and niether does the prompt unless it's a blankspace in a string. I have tried select and select2, didn't make any difference either.
Does anyone have any idea of how to do this properly?
I thought I'd just leave an answer here in case anyone stumbles upon the same problem in the future, with this ember version.
Inspired by Lux comment, I passed an object as the first object in the content array instead, I did this using unshiftObjects which is supported by this ancient ember version believe it or not. (The first object is what is shown in the select if there's data in it & there's no prompt in the select view)
Code example of what I did:
this.set('countries', countries.unshiftObjects({id:-1, name:"Select country.."}));
And a validation that checks if a post is made with id -1 and in that case treat it as if nothing was selected.
Note that there are probably better ways to go about this & this is a workaround, but it's what worked for me :)

How to render Ember component on same line

This Ember template code...
<div class="detail bedrooms">
<span>Number of bedrooms:</span> {{rental.bedrooms}}
</div>
<div class="detail temperature">
<span>Current Temperature:</span> {{city-temperature location=rental.city}}
</div>
...results in this rendering...
How could one get the "25C" text to render on the same line as "Current Temperature" in the same way that "San Francisco" is on the same line as "Location"?
I have tried getting the city-temperature component to return only text, but (secondary question here) is it even possible for a component to return only text if the text is from a remote ajax request since the promise seems to need a DOM element to append to?
This Ember app is available here on GitHub. It's a modified version of the official Ember.js tutorial app with this "Current Temperature" detail added.
The problem is that; city-temperature is a component; and by default ember components is assigned div as their tags. Due to this; the content of city-temperature starts at a new line.
What can you do? Play with css and make sure div tag of city-temperature does not start at a new line; but instead floating right within the owner div. The second option is making city-temperature component tagless; so that it does not start at a new line. To achieve that; you can just declare:
tagName: ''
within city-temperature.js. You can see the following twiddle to see the second option I mentioned.
After reading your comments; I have forked your repository and made minor modifications to achieve what you want. You can check my repository and my corresponding commit to see what I changed.
Basically; I really did not like the idea that weather service is returning a DOM element. I have changed it to return an instance of ember promise (I mean Ember.RSVP.Promise). Within city-temperature.js I just set a retrieved weather value from weather service and set it to the component instead of making DOM modification. Finally; I modified city-temperature.hbs to render weatherValue and added a simple css item in order to prevent weather-container div to insert a new line break.
I am not sure; whether you will like my solution or not; but I guess you will retrieve the visual appearance you want. You can always rely on promises for async tasks; you do not need to create DOM elements and pass them around to components and append them to somewhere within DOM tree of the corresponding component. I believe one of the reasons we are making use of a framework like Ember is to prevent such DOM modifications. Best regards.
An ember component adds a div by default. If you don't want to add this div tag, you need to set tagName to an empty string.
That's called tagless component.
Further, for your case, you can give a tagName='span' so you will not need a span in your template.
export default Ember.Component.extend({
tagName: 'span',
classNames: ['weather-container'],
weather: Ember.inject.service(),
//rest of your code...
});

emberJs giving different routes to links

I got a page that includes 15 pictures and I must redirect user to the details page if one of them is clicked. so, I have 15 different routes like 1,2,3,...15. But as I know, I cant give dynamic variable to #link-to helper. So how am I gonna make every picture go to its own route? this is how my index page .hbs looks like :
{{#each model as |rentalUnit|}}
{{rental-listing rental=rentalUnit}}
{{/each}}
{{outlet}}
This is how I print every picture. And this is how am I trying to go to routes :
{{#link-to "???"}}<img src={{rental.image}} width="200">{{/link-to}}
so, there is ??? because I dont know what to do. Thanks!
Well, first why not use a dynamic segment in your route? Like this:
this.route('image', {path: '/images/:id'});
But what you want can be done by just passing a variable, not a string to the link to helper as first argument:
{{#link-to target}}
Where {{target}} would print your route name. So target is a variable here, not a string.
Checkout this twiddle.

Simple search with Emberjs not working

I am trying to implement a simple search feature, which will filter the results and update the listing.
I tried almost every single tutorial out there, every tutorial seems to be working with its jsfiddle but when I apply the same thing on my project, it does not work at all.
Here is what I am having as a first problem, my search field does not seems to be bound with computed property in controller.
I also tried it as a component but again same issue, if I type anything in search field it does not reflect anything.
Let me share my code here,
input type="text" value=searchText placeholder="Search..."
searchResults: ( ->
console.log "On every key press it should come here.."
model = #get('model')
searchText = #get('searchText')
filterByPath = #get('filterByPath')
visualPath = #get('visualPath')
if searchText
searchText = searchText.toLowerCase()
model = model.filter(item) ->
Ember.get(item, filterByPath).toLowerCase().indexOf(searchText)>= 0
model.getEach(visualPath)
).property('searchText')
Tried almost the same thing with component, but no luck so far. I am not using handlebars but Emblemjs.
You actually need to use computed property in template if you want it to be compiled, then recompiled etc. It is somewhat lazily evaluated so you can't debug that without using this in template first or calling from JavaScript code. So basically you need to use searchResults in your template first.
In demo there was model instead of searchResults. I guess in your application you have similiar setup and same bug.
Fix:
{{#each searchResults as |item|}}
<li>{{item}}</li>
{{/each}}
Working demo.

Ember saving one to one, using promises

im trying to save a few models with one to one relation which initializes on a single controller action. Ive split things into small functions to use promises. I've been trying to make it work for almost a week and cant find the solution. I've also made a jsbin:
http://jsbin.com/enoYONAv/1/edit
Instead of valueBinding you can use selectionBinding in your Ember.Select, to retrieve the selected model directlly instead of your id. For example:
{{
view Ember.Select
prompt="Gender"
contentBinding="genders"
optionValuePath="content.id"
optionLabelPath="content.type"
selectionBinding="selectedGender"
}}
So in you action you can do:
var gender = this.get('selectedGender');
...
var hash = {
name : personName,
gender : gender,
organization : organization
};
this.savePerson(hash).then(this.saveAgentAssociation(agentAddress));
This is your updated jsbin please give a look http://jsbin.com/efeReDer/1/edit