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
Issue 96 #195
Issue 96 #195
Changes from 4 commits
049c4e2
6855ed6
2e143ff
769487a
a3b8192
bd2a720
48d5c57
6c48c57
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
module Pakyow | ||
module Presenter | ||
class Form | ||
|
||
attr_reader :form_view, :context | ||
|
||
def initialize(view, context) | ||
@form_view = view | ||
@context = context | ||
end | ||
|
||
def create(*binding_args, &block) | ||
bind_data(binding_args, block) do |routes, view| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It isn't obvious from the name of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, tough. Yielding routes here doesn't give us much, so maybe it can be moved. Off the top of my head, what about |
||
view.attrs.action = routes.path(:create, request_params) if routes | ||
end | ||
end | ||
|
||
def update(*binding_args, &block) | ||
bind_data(binding_args, block) do |routes, view| | ||
if routes | ||
route_params = request_params.merge( | ||
:"#{scoped_as}_id" => view.attrs.__send__('data-id').value | ||
) | ||
|
||
view.attrs.action = routes.path(:update, route_params) | ||
end | ||
|
||
view.prepend( | ||
View.new('<input type="hidden" name="_method" value="patch">') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's move the HTML string to a constant. |
||
) | ||
end | ||
end | ||
|
||
private | ||
|
||
def bind_data(binding_args, block) | ||
bind(*binding_args) do |view, data| | ||
routes = Router.instance.group(scoped_as) | ||
|
||
yield(routes, view) | ||
|
||
return if block.nil? | ||
|
||
if block.arity == 1 | ||
view.instance_exec(&block) | ||
else | ||
block.call(view, data) | ||
end | ||
end | ||
end | ||
|
||
def request_params | ||
context.request.params | ||
end | ||
|
||
def method_missing(method, *args, &block) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you provide some thoughts on why we need this? I had assumed that any changes to the form would occur inside the block for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah this is just to allow users to make further changes on the order of normal view manipulation. It may not be strictly necessary, but it seemed consistent with View#bind. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you provide an example? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. Thought about it for a bit, but what about nested forms? <form data-scope="album">
<input data-prop="name" type="text" />
<div data-scope="image">
<input data-prop="name" type="text" />
</div>
</form> data = { id: 1, name: 'a', images: [{ id: 1, name: 'b' }, { id: 2, name: 'c' }] }
view.form(:album).update(data) do |view, data|
view.scope(:image).apply(data[:images]) do |fields, image|
fields.prop(:name).attrs.name = "album[images][#{image[:id]}[name]"
end
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or do you think that this would be better placed in a binding? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You wouldn't need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. My original idea was for form to act like a view, but with extra form actions, but since the user can access the view maybe that can be the solution to the problem above as well, so that the example above would simply be: data = { id: 1, name: 'a', images: [{ id: 1, name: 'b' }, { id: 2, name: 'c' }] }
form = view.form(:album)
form.update(data)
form.view.scope(:image).apply(data[:images]) do |fields, image|
fields.prop(:name).attrs.name = "album[images][#{image[:id]}[name]"
end |
||
if form_view.respond_to?(method) | ||
form_view.__send__(method, *args, &block) | ||
else | ||
super | ||
end | ||
end | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's rename
form_view
toview
. It's already scoped within the form, so it seems redundant.