Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling User Input #3

Open
Tracked by #1
jgaskins opened this issue Sep 10, 2016 · 0 comments
Open
Tracked by #1

Handling User Input #3

jgaskins opened this issue Sep 10, 2016 · 0 comments
Labels

Comments

@jgaskins
Copy link
Member

Your components receive user input via events. When a user clicks a button, a click event is fired on that button, for example. You can respond to those events by passing DOM event names as properties of the element and a handler for that event as its value. The handler can be any call-able object, including procs, lambdas, methods, and even just a service object:

class ClickCounter
  include Clearwater::Component

  def initialize
    @click_count = 0
  end

  def render
    div([
      h1(@click_count),
      button({ onclick: proc { |event| clicked! } }, 'Proc'),
      button({ onclick: ->event { clicked! } }, 'Lambda'),
      button({ onclick: method(:clicked!) }, 'Method'),
      button({ onclick: ClickHandler.new(self) } }, 'Service object'),
    ])
  end

  def clicked!(event=nil)
    @click_count += 1
    call # Re-render the app after updating state
  end
end

ClickHandler = Struct.new(:counter) do
  def call(event)
    counter.clicked!
  end
end

Notice the four buttons all have different onclick values. The first two just use two different types of procs, the third uses a bound method object, and the last one uses an instance of a class we defined ourselves. Any object that responds to call can be used as an event handler.

In that example, we didn't use the event object that was passed in because we didn't need to. The only context we needed was that the button was clicked. But sometimes you need to use the event to get more insight into the event. For example, if we're filtering a list of items:

class UserList
  include Clearwater::Component

  attr_reader :users

  def initialize(users)
    @users = users
  end

  def render
    div([
      input(
        type: :search,
        oninput: method(:filter),
      ),
      ul(filtered_users.map { |user|
        li(user.name)
      }),
    ])
  end

  def filtered_users
    users.select { |user| user.name =~ @filter }
  end

  def filter(event)
    # event.target is the DOM element that triggered this event
    # event.target.value is the string value of the input element.
    #   - it could be `nil` in some browsers, so we cast it to a string with `to_s`
    @filter = RegExp.new(event.target.value.to_s)
    call
  end
end

This component takes an Enumerable list of user objects and renders a ul that contains an li for each user whose name matches the filter query. When you type into the search field, it changes the filter to the value of that search field and re-renders the app with the new filter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant