Form_with trong Rails 5.1 với form_for và form_tag
Bài đăng này đã không được cập nhật trong 7 năm
form_for
và form_tag
đã rất quen thuộc trong các phiên bản Rails, nhưng chúng sẽ được thay thế bởi form_with
trong tương lai (rails 5.1). Dưới đây giới thiệu về sự khac nhau giữa form_for
, form_tag
và form_with
với các ví dụ đơn giản.
Một cú pháp cho tất cả
Trước đây, khi bạn muốn tạo một form nhưng không có đối tượng cho nó, bạn sử dụng form_tag
:
<%= form_tag users_path do %>
<%= text_field_tag :email %>
<%= submit_tag %>
<% end %>
Khi có một đối tượng, bạn sử dụng form_for
:
<%= form_for @user do |form| %>
<%= form.text_field :email %>
<%= form.submit %>
<% end %>
Như bạn đã thấy, chúng ta sử dụngform builder field helper
với form_for
nhưng lại không sử dụng với form_tag
, vì vậy cú pháp của cả 2 forms này là khác nhau.
Nhưng với form_with
, chúng ta sử dụng form builder
cho tất cả các field.
form_with
khi không có đối tượng:
<%= form_with url: users_path do |form| %>
<%= form.text_field :email %>
<%= form.submit %>
<% end %>
và khi có đối tượng:
<%= form_with model: @user do |form| %>
<%= form.text_field :email %>
<%= form.submit %>
<% end %>
Khi bạn thêm các đối số cho đối tượng, các scope và url sẽ tự động điều hướng từ đó, nó hoạt động giống như form_for
.
Không tự động thêm id và class cho thẻ form và form field
form_tag
và form_for
tự động tạo id
cho các trường của form, form_for
còn thêm cả cho thẻ form:
<%= form_for User.new do |form| %>
<%= form.text_field :email %>
<% end %>
sẽ tạo ra:
<form class="new_user" id="new_user" action="/users" ...>
...
<input type="text" name="user[email]" id="user_email" />
</form>
Với form_with
, bạn phải tự thêm các id
và class
bằng tay:
<%= form_with model: @user do |form| %>
<%= form.text_field :name %>
<%= form.text_field :email, id: :email, class: :email %>
<% end %>
Tạo ra:
<form action="/users" ...>
...
<input type="text" name="user[name]" />
<input id="email" class="email" type="text" name="user[email]" /> </form>
Đừng quên thêm các id
cho các trường của form nếu bạn muốn các label
có thể hoạt động:
<%= form_with model: @user do |form| %>
<%= form.label :name %>
<%= form.text_field :name, id: :user_name %>
<% end %>
Thuộc tính id và class của form không được đóng gói nữa Trước đây:
<%= form_for @user, html: { id: :custom_id, class: :custom_class } do |form| %>
<% end %>
Mới:
<%= form_with model: @user, id: :custom_id, class: :custom_class do |form| %>
<% end %>
Các trường của form không cần phải tương ứng với các thuộc tính của model Trước đây:
<%= form_for @user do |form| %>
<%= form.text_field :email %>
<%= check_box_tag :send_welcome_email %>
<% end %>
Mới:
<%= form_with model: @user, local: true do |form| %>
<%= form.text_field :email %>
<%= form.check_box :send_welcome_email %>
<%= form.submit %>
<% end %>
Chú ý rằng send_welcome_email
sẽ được gửi tới controller dưới dạng params params[:user][:send_welcome_email]
vì vậy, bạn vẫn có thể sử dụng check_box_tag
thay vì form.check_box
nếu bạn cần.
Tất cả các form đều mặc định ở chế độ remote
Tất cả các form được tạo bởi form_with
sẽ được submit mặc định bởi request XHR(Ajax). Bạn không cần thêm remote: true
như khi sử dụng form_for
và form_tag
và chỉ cần tạo thêm một template respond Javascript để nó có thể hoạt động.
Nếu bạn không muốn sử dụng remote cho form, bạn có thể thêm local: true
như sau:
<%= form_with model: @user, local: true %>
<% end %>
Trên đây giới thiệu một vài sự khác nhau của form_for
, form_tag
và form_with
, bạn có thể đọc thêm về from_with
tại:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with
All rights reserved