How to create a search box and display result


#1

I have to say i spent quite some time on stackoverflow, emberjs.com guide and googling away and most exemple assume that you know much about ember… Well this is my first attempt to build a (phonegap) mobile app with ember and i already lost my mind. Ember seems very powerfull and does so much but i am really struggling to build my searchbox. I am using ember data and the RESTadapter, the app will live on the device (not on any server) I have a model (App.products) , a couple of pages (index, about) and from any of these pages i have a searchbox where to find a product. typing a name or a category should return a list of result on it’s on page, and clicking each result go to the single product… This is quite basic but i am not sure how to do it…

I have the simple pages working products (which i dont actually need), index and about. If someone could point me to the right direction that could be great…


#2

I’d suggest creating a helper. Here’s a simple searchable field example given by Tom and Yehuda.

http://jsbin.com/ulukep/1/edit


#3

Ok i know it has been a couple of weeks now (i have been working on another project) and thank you for your input. My need is more like so: I use ember data and the DS.RESTAdapter. I have a search box on my “application” template with the action “doSearch” . in my applicationController i have “doSearch” function and from there i aint sure how to get the data, right URL path that would please ember data and how to output the result in my template. In other words, I AM LOST…!!!

//in applicationController
doSearch: function() {
// the current value of the text field
	var query = this.get('search');
	//this.transitionToRoute('search', { query: query });

    this.set('searchQuery', query);
    this.transitionToRoute('search', query);

}

//in router
this.route("search", { path: "/search/:query" })


//in index.html data-template-name="searchpage"
<h1>Search</h1>
<p>You searched for: "{{application.searchQuery}}"</p>

#4

Add needs 'search' to your applicationController to have access to searchController's properties , add query attribute to your searchController, in doSearch action set the query attribute of searchController like so: this.get('controllers.search').set('query', query). Then on the searchRoute you will need specify a model hook:

  model: function(params) {
    return App.Model.find(params);
  }

Then reopen your model:

App.Model.reopenClass({
  find: function(params) {
    ...
  }
});

#5

Thanks xAmenrax,

I had followed this example (http://stackoverflow.com/questions/16014743/emberjs-how-to-handle-transitionto) and had it working to a point. But wasn’t sure what the response object should look like ?

{
"search": [
    {
        "id": 1
    },
    {
        "id": 2
    },
    {
        "id": 3
    }
]
}

and in the template is it a simple each loop like any other model ?


#6

Ok i am making good progress. return data is not an object but just the array inside.

[ { "id": 1 },
{ "id": 2 },
{ "id": 3 } ]


App.Search = DS.Model.extend();

App.Search.reopenClass({
find: function(params){
	var result = Ember.ArrayProxy.create({content: []});
	var _this = this;
	$.getJSON('http://site.com/search/' + params.query, function(data) {
result.set('content', data);
	});
	return result;
}
});


App.SearchRoute = Ember.Route.extend({

model: function(params) {
	//return App.Product.search(params);
	return App.Search.find(params);
},

deserialize: function(params) {
    this.controllerFor('application').setProperties({
        searchQuery: params.query,
        search: params.query
    });
},

renderTemplate: function() {
    this.render('searchpage', { into: 'application' });
}
});

App.ApplicationController = Ember.Controller.extend({
doSearch: function() {
var query = this.get('search');

    this.set('searchQuery', query);
    this.transitionToRoute('search', query);

},
});

So this works great on page refresh but not on transitionToRoute the find function doesn’t get called and i get the following error message

Assertion failed: an Ember.CollectionView’s content must implement Ember.Array. You passed BLABLA Uncaught TypeError: Object BLABLA has no method ‘addArrayObserver’


#7

I found this pretty trivial to implement in a simple way - the search is triggered live on typing and results come back instantly. Hope this helps someone.

App.PlayersController = Ember.ArrayController.extend({
  search: function() {
    query = this.get('q');
    console.log('PlayersController: ' + query);
    if(query != "") {
      var that = this;
      jQuery.getJSON("/api/v1/players/search.json?q=" + query, function(data) {
        that.set('results', data['players']);
      });
    }
  }
});

{{view App.TextField valueBinding="q"}}
<table class="table table-striped table-hover table-condensed">
  <thead>
    <tr>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    {{#each player in controller.results}}
    <tr>
      <td>
        {{#linkTo "player" player.id}}{{player.first_name}} {{player.last_name}}{{/linkTo}}
      </td>
    </tr>
    {{/each}}
  </tbody>
</table>

#8

I like this approach however it looks like you will be making a GET request every time you type a character, it’d be nice to fetch everything initially and just filter through the results as you type, I’ll try to update the code to achieve this

PD: I made this roughly based in the code above but only requires a single request to fetch all items and then filters through the results as you type, I’m new to ember so I’m sure this can be improved and also I agree that making it a handlebar helper or component helps with re-usability.


#9

It does indeed make a GET request every keystroke, but it’s easy enough to only start that after N characters, or make the search respond to an {{action}}.

I should point out that this is search - finding something, whereas loading in all the data first is filtering - sifting - and I would consider that a completely different thing :slight_smile:

Be careful with pre-loading too much data - Ember will not automatically reload partially-complete models in case you were thinking of filtering through, say, only the first names of a User model.


#10

That’s nice to know I didn’t think about it thanks!


#11

Ok i am still banging my head so far. What i want/need seems pretty normal but it looks like Ember data cannot do it for me(PLEASE correct me if i am wrong!)

I have an application template with a Ember.TextField in it to allow me to search/filter all my Products . I have to many product to list them all so the only way to see a product list is via this search. The search should return an array of product and in my search template i list them with a link to a single product. I also need to show the single product inside the search outlet so the search list is style visible.

I have managed to make some of it work. I do a search which sends to url #/search/milk and that does an ajax request, return the result. then each model links to #/product/:product_id so it means i change page or i need to keep the search result list and unique product beside each other…

What i also find weird is that u can’t use ember data to fetch my search query…


#12

any update on this? I know that this discussion is a year old but it’s still not answered…