0
votes

I have an ember component which wraps a text field. When a user types I want to fire of a search action.

#search-box.js.coffee
App.SearchBoxComponent = Ember.Component.extend
  classNames: ['form-group', 'has-feedback']
  term: ""
  placeholder: "Search"

  actions:
    search: ->
      console.log "Searching..."

# search-box.emblem
= input type="text" value=term class="form-control" placeholder=placeholder keyUp="search"

This maintains the binding between value and term, but the keyUp event goes to the Ember Input component and does not bubble to the search-box component. If I drop the = and instead use a standard HTML input, I get the action sent to the right component, but the binding breaks and I lose my search term.

What's the proper way to use an input with an action inside a component?

EDIT: Another approach

Trying to do it with JQuery, with the added difficulty of searching after a specified period of inactivity (a second, in this case):

App.SearchBoxComponent = Ember.Component.extend
  classNames: ['form-group', 'has-feedback']
  delay: 1000
  didInsertElement: ->
    $input = @$('input')
    $input.on 'keyup', =>
      clearTimeout(timer)
      if $input.val
        console.log this
        timer = setTimeout(@_performSearch, @get('delay')
  _performSearch: ->
    console.log this
    console.log "Searching for #{@get('q')}"

When _performSearch is called, this is now window and has lost the context of the Ember class. I also tried making everything fat arrows to make absolutely sure no function changes the context of this, but to no avail. It will work if I make an anonymous function inside of the setTimeout call, but not if I call a method on the ember object.

2
good luck using ember's keyUp, i have never got that to work... but perhaps if you make a component that extends the actual textfield view. you can use the actual javascript keyup event to trigger some behavior?Grapho

2 Answers

0
votes

I've implemented the same search mechanics by observing value of search_term (term in your code). I think you could try to do it that way. You need to set observer in App.SearchBoxComponent, firing search action from there, if !Em.Empty(this.get('term').

0
votes

You could set up a jQuery mouse event in the didInsertElement hook of the component:

App.SearchBoxComponent = Ember.Component.extend
  classNames: ['form-group', 'has-feedback']
  term: ""
  placeholder: "Search"

  didInsertElement: ->
    @$('input').keyup => 
      console.log 'Searching...'

Regarding your second approach, you can specify the context of the function by using Ember.run.later. Note: you were also missing closing parentheses after your call to setTimeout.

Replace

timer = setTimeout(@_performSearch, @get('delay'))

with

Ember.run.later(@,@_performSearch, @get('delay'))