New form views in Pakyow

The other day, I decided to tackle an open issue for Pakyow on github. Up to now, there has been no clear way to set up a form view in Pakyow. The goal is for the form’s action attribute to be set to the correct route path depending on what data is bound to the form. Also if the form should be sent with an HTTP method other than the default POST, then a hidden input “_method” should also be set.

Assuming we have this form for a “user” with a field for the user’s name:

<!-- example of a scoped form in pakyow -->
<form data-scope="user">
<input type="text" data-prop="name" />
</form>

You could very easily manipulate the view object yourself, but that would get pretty tedious to do all the time. The example below sets the action for the form (create a new user):

# Set the action on the form
get :new, '/new' do
view.scope('user').bind(User.new) do |view, data|
view.attrs.action = router.group(:user).path(:create)
end
end

Likewise, there has been form support for updating and creating resources via “restful” bindings. Since Pakyow v 0.11, you can create a resource this way:

# Set up for a pakyow restful resource 
# (previously done by creating restful routes/bindings separately)
Pakyow.app.resource :user, 'users' do
# specify route logic here
end

This will create bindings for the “user” scope which will set up the proper action when the scope is bound with an object that with an “:id” (update action) or without (create action).

That works great, but maybe you don’t want to create a whole new restful resource just to have a working form. Or maybe you want to break away from restful routes. This issue hopes to address the problem by providing a new api for managing forms.

Introducing the Pakyow::Presenter::Form class, which is here to help you manage your form views. In your routes, you can get a Form object by using the ViewContext#form method.

get :new, '/new' do
view.form('user').create(User.new)
end
post :create '/' do
# ...
end
get :edit, '/:id/edit' do
view.form('user').update(User.find(params[:id])
end
patch :update '/:id' do
# ...
end

The #form method works like the #scope method, but gives you back a Form object that you can use to #create or #update models. These methods will set up the form action and other attributes like the “_method” input which for #update is set to PATCH. You can also provide a block, just like with View#bind, so you can take full control if you need to.

The implementation to this is still a work in progress, so there may still be some changes to how the Form object methods work. But what is clear is that for Pakyow v 1.0, we should expect a new api for managing forms.