Simple search with Emberjs not working - ember.js

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.

Related

Ember computed property on a controller not bound in template

I'm trying to implement a password strength checker that will update on every key press. My template looks like this:
{{input type="password" id="password" value=password }}
My controller looks like this:
App.SignupController = Ember.Controller.extend
passwordStrength: ((key,val) ->
# check strength if val is defined
return
).property('password')
passwordStrength is never called when text is entered in the field.
However, if I rename the method to just password and remove the computed property's name, it does work:
App.SignupController = Ember.Controller.extend
password: ((key,val) ->
# check strength if val is defined
return
).property()
I'd rather understand why the former was not working though, and use a more sensibly named method too.
I've created a jsbin for you to look at that is working and updating when the password is updated. I think I know why this is not working for you. in my js bin here http://emberjs.jsbin.com/gekofo/4/edit?html,js,console,output You will notice that only the observer console.logs. Whereas in your program I would imagine you maybe aren't displaying the passwordStrength value. If you add {{passwordStrength}} into the template in my bin, you will see that the property gets updated. So it looks like you may want to use the passwordStrength2 that i have written, because it will update whether it is displayed in the DOM or not.
In short use this:
passwordStrength2: function() {
//check strength if val is defined
console.log("OBSERVER::", this.get('password.length'))
return this.get('password.length');
}.observes('password')
NOT:
passwordStrength: function() {
//check strength if val is defined
console.log("PROPERTY::", this.get('password.length'))
return this.get('password.length');
}.property('password')
Also I do not know coffeescript, so sorry my answer is in javascript.

Ember/Handlebars: compare variable with string

I need to display some block depending on the current views variable in comparison to some string:
PSEUDO code is:
{{#if view.someVariable "desiredValue"}}
Hurray desiredValue exists in this view!
{{else}}
Sorry, doesn't match...
{{/if}}
Of course it doesn't work as if statement allows only one param. I tried with custom registerHelper of Handlebars, but it doesn't resolve the view.someVariable, instead uses it as a string (although view.someVariable is defined and has value).
Finally I also tried with Handlebar's registerBoundHelper - it resolves the params BUT doesn't support Handlebar's blocks, what's more tries to resolve the string as an object, so fail again. Pure madness!
My views are very dynamical they depends on many factors also from backend and approach from the pseudo code would be perfect for resolving it. Is there any way to do that?
Edit:
There is a sample of what I want ... http://jsfiddle.net/biesior/dMS2d/ looks quite trivial...
[if] statement inside the each is pseudo code of course
You can just declare a computed property, something like isDesired on your view, which would compare someVariable to your string:
App.MyView = Ember.View.extend({
// ...stuff...
isDesired: Ember.computed.equal('someVariable', 'desiredValue')
});
And have a simple conditional in the template:
{{#if view.isDesired}}
Hurray desiredValue exists in this view!
{{else}}
Sorry, doesn't match...
{{/if}}

How to create a directory-like structure with meteor templates?

Consider this mockup of my intended output:
The data structure behind this in a Mongo DB looks like this - I did not nest the subcategories inside the document because I still want to be able to update subdocuments atomically - and I also want to allow a dynamic amount of layers below. From what I've seen, Mongo currently does not allow for easy, dynamic access of nested documents.
topmost_category = {
_id : "foo",
category_name : "Example",
parent_category: null,
subcatories: [ "sub_foo1", "sub_foo2", ... ]
}
child_category = {
_id = "sub_foo1",
category_name : "Example 2",
parent_category: "foo",
subcategories: []
}
The underlying HTML consists simply of nested -branches. The currently selected category gets an "active" class, and the icons in front are named "icon-folder-close" and "icon-folder-open" (<i class="icon-folder-close"></i>).
Now, I could use the answer to this to create a complete tree-like structure. However, all the branches would be "open". How do I make it so that only the currently selected branch is visible like shown in my mockup (and still have it reactive to boot)?
You can see the implementation of a very similar approach to that described by Hubert here:
http://www.meteorpedia.com/read/Trees
It's the code to the (working) category browser functionality of the wiki (you can see a demo there).
The main difference to Hubert's answer is that it uses a publish/subscribe with a session variable to fetch the data of opened children in real time.
The easiest way would be to add a boolean flag for branches denoting whether or not they belong to current path, and therefore should be open.
<template name="branch">
{{#if open}}
<div class="openBranch">
...
{{#each children}}
...
{{/each
</div>
{{else}}
<div class="closedBranch">
...
</div>
{{/if}}
</template>
Now, the setting and management of this flag depends on the logic of your application. Where do you store the currently selected branch?
I assume the state is limited to a single client. In this case, one solution is to:
maintain an array of opened branches ids, scoped to a single file,
implement the open flag as a helper:
Template.branch.open = function() {
return _.indexOf(openedBranches, this._id) !== -1;
}
when user changes selection, clear the array and populate it with path from the selected branch to the top.

Setting selected entry using helper.options?

Im am using Play 2.0.4 and
helper.options(myitems)
in my template (inside of a helper.select)
In this case, how can I define the default selected entry, which shall be one entry out of myitems? Thanks for any hint!
A little bit more about my case:
Imagine a news archive, showing all news titles. This news archive uses pagination, pagination uses GET to pass the next/previous page number.
The play framework however will only correctly select the currently selected "select" item (here: news category) when a POST request was used - while pagination uses GET!
Intended behaviour: While a filter is applied / a specific news category is selected, this shall always be visible to the user by preselecting the currently selected news category in the "select" form.
A "screenshot" for illustration:
So, anyone having a good idea on how to cope with this problem? Any way to tell Play manually which entry from the "select" form it shall select? '_default always adds a new entry instead of selecting one out of the given options ): Would be great, if one wouldn't have to build the complete "select" form manually.
Try passing '_default option to select helper:
#import views.html.helper._
#select(form("email"), options(List("first", "third")), '_default -> "second")
It seems, unfortunately, the only way to figure it out is to look up the source.
Update:
Specifying _default property doesn't set selected attribute on option tag. It looks like the only way to preselect entry is to pass prefilled form to the template. For example, suppose you have following form:
case class RegInfo(email: String, color: String)
private val registrationForm = Form(
mapping(
"email" → email,
"color" → nonEmptyText(minLength = 5, maxLength = 32)
)(RegInfo.apply)(RegInfo.unapply)
)
Then in the action prefill form before passing to the view:
def create = Action {
Ok(html.create(registrationForm.fill(RegInfo("user#qwe.com", "blue"))))
}
Then in template use helper:
#select(form("color"), options(List("red", "green", "blue")))
And value will be preselected.
Ended up with the pragmatic approach:
<select id="myfield" name="myfield" >
<option class="blank" value="">-- All items --</option>
#for((key, value) <- MyModel.options) {
#if(key == GETValuePassedToTemplate) {
<option value="#key" selected>#value</option>
} else {
<option value="#key">#value</option>
}
}
</select>
Still wondering if there is a better option / way to do it.
Actually, there is a nicer solution to it. If you call the template having the form partially bound you will achieve your goal. Here's the code for your controller:
Ok(views.html.myForm(myForm.bind(
Map("fieldName1" -> "value1",
"fieldName2" -> "value2"))))
Make sure you map fieldnames to the values of the options you want pre-selected.
Still wondering if there is a better option / way to do it.
Well, if your not hell-bent on using play to solve this particular problem, you could always solve it using JavaScript and jQuery:
$(function () {
$('#yourSelect_id').val(5);
}
Where your select options each has values and the one option you whish to pre select has value 5.

Ember Data: Proper Way to Use findAll

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.