(1)在布局文件中讲弹出层代码和主体代码分开
</footer>
<%= yield(:page_modal) if content_for?(:page_modal) %>
<%= javascript_include_tag "application" %>
<%= yield(:page_javascript) if content_for?(:page_javascript) %>
</div> <!-- /container -->
</body>
</html>
(2)改写添加商品的时候按钮的方法,增加data属性,里面设定当按钮点击的时候,
打开哪一个model,在model的代码里,调用form这个局部模板,
在下面的js代码里声明这个model,并且声明这个model在加载的时候不显示。
app/views/products/index.html.erb
<%- model_class = Product -%>
<div class="page-header">
<h1><%=t '.title', :default => model_class.model_name.human.pluralize.titleize %></h1>
</div>
<table class="table table-striped">
<thead>
<tr>
<th><%= model_class.human_attribute_name(:id) %></th>
<th><%= model_class.human_attribute_name(:name) %></th>
<th><%= model_class.human_attribute_name(:price) %></th>
<th><%= model_class.human_attribute_name(:description) %></th>
<th><%= model_class.human_attribute_name(:created_at) %></th>
<th><%=t '.actions', :default => t("helpers.actions") %></th>
</tr>
</thead>
<tbody id="productsTable">
<%= render @products %>
</tbody>
</table>
<%= link_to t('.new', :default => t("helpers.links.new")),
new_product_path,
:class => 'btn btn-primary',
data: {toggle: "modal", target: "#newProductFormModal"} %>
<%= content_for :page_modal do %>
<div class="modal fade" id="newProductFormModal" role="dialog" aria-labelledby="myModalLabel"
aira-hidden="true">
<div class="modal-dialog">
<%= form_for @product, remote: true, :html => {:class => 'form-horizontal',
id: "newProductForm"} do |f| %>
<div class = "modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
<h4 class="modal-title">添加一个商品</h4>
</div>
<div class="modal-body">
<%= render partial: "input", locals: {f: f} %>
</div>
<div class="modal-footer">
<%= link_to t('.cancel', :default => t('helpers.links.cancel')), '#',
:class => 'btn btn-default', data: {dismiss: "modal"} %>
<%= f.submit nil, :class => 'btn btn-primary', :data => { :"disable-with" => "请稍等..."} %>
</div>
</div>
<% end %>
</div>
</div>
<div class="modal fade" id="editProductFormModal" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<%= form_tag "", method: :put, remote: true, data: { type: "json" }, id: "editProductForm", class: "form" do %>
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">编辑一个商品</h4>
</div>
<div class="modal-body">
<div class="alert alert-dismissible alert-danger" id="alert-content">
<button type="button" class="close" data-dismiss="alert">×</button>
<div id="msg"></div>
</div>
<div class="form-group">
<%= label_tag "product[name]", Product.human_attribute_name("name"), :class => 'control-label' %>
<%= text_field_tag "product[name]", "", :class => 'form-control', id: "editProductName" %>
</div>
<div class="form-group">
<%= label_tag "product[description]", Product.human_attribute_name("description"), :class => 'control-label' %>
<%= text_field_tag "product[description]", "", :class => 'form-control', id: "editProductDescription" %>
</div>
<div class="form-group">
<%= label_tag "product[price]", Product.human_attribute_name("price"), :class => 'control-label' %>
<%= text_field_tag "product[price]", "", :class => 'form-control', id: "editProductPrice" %>
</div>
</div>
<div class="modal-footer">
<%= link_to t('.cancel', :default => t("helpers.links.cancel")), '#', :class => 'btn btn-default', data: {dismiss: "modal"} %>
<%= submit_tag t('.confirm', :default => t("helpers.links.confirm")), :class => 'btn btn-primary', :data => { :"disable-with" => "请稍等..
</div>
</div>
<% end %>
</div>
</div>
<% end %>
<%= content_for :page_javascript do %>
<script>
$('#newProductFormModal').modal({
show: false,
})
$('#editProductFormModal').modal({
show: false,
})
</script>
<% end %>
(3) 点击新建我们可以看到弹出层的效果已经实现了,但是form里又包含了相同的功能的按钮,
这个时候我们需要对form再进行一个拆解,将它的控件部分提供给弹出层。
新建模板app/views/products/_input.html.erb
<div class="control-group">
<%= f.label :name, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :name, :class => 'form-control' %>
</div>
<%= error_span(@product[:name]) %>
</div>
<div class="control-group">
<%= f.label :price, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :price, :class => 'form-control' %>
</div>
<%= error_span(@product[:price]) %>
</div>
<div class="control-group">
<%= f.label :description, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :description, :class => 'form-control' %>
</div>
<%= error_span(@product[:description]) %>
</div>
在form里引用这个模板 app/views/products/_form.html.erb
<%= form_for @product, :html => { :class => "form-horizontal product" } do |f| %>
<% if @product.errors.any? %>
<div id="error_expl" class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title"><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h3>
</div>
<div class="panel-body">
<ul>
<% @product.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
</div>
<% end %>
<%= render partial: "input", locals: {f: f} %>
<%= f.submit nil, :class => 'btn btn-primary', :data => { :"disable-with" => "请稍等..." } %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
products_path, :class => 'btn btn-default' %>
<% end %>
(4)刷新页面,再次点击新建按钮,弹出层效果已经实现了,在弹出层新建一个商品,可以看到页面没有关闭,
页面上也没有显示新添加的商品,进到log里可以看到,刚才我们提交的是一个post操作,产生的是js响应,
在完成之后,它返回的也是一个js响应。在脚手架为我们创建代码的时候,里面并没有添加如何执行js的响应,
我们需要手动添加一个,比如在create方法里,进入respond_to,
def create
@product = Product.new(product_params)
respond_to do |format|
if @product.save
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: @product }
else
format.html { render :new }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
format.js
end
end
def edit
respond_to do |format|
format.html
format.json {render json: @product, status: :ok, location: @product }
end
end
def update
respond_to do |format|
if @product.update(product_params)
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
format.json
else
format.html { render :edit }
format.json { render json: @product.errors.full_message.join(', '), status: :error}
end
format.js
end
end
def destroy
@product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
format.js
end
end
创建新文件app/views/products/create.js.erb ,这样做的好处是,我们可以在js文件里使用erb语法,
在文件中先判断商品是否保存成功,如果保存失败,需要演示它的错误信息,
如果保存成功,需要先将商品添加到列表里,然后关闭这个弹出层,最后将这个弹出层里的表单重置一下,
否则再次点击添加按钮的时候,刚才添加的文字还在弹出层表单里。
<% if @product.errors.any? %>
$('#newProductInput').prepend('<%= j render "errors" %>');
<% else %>
$('#productsTable').prepend('<%= j render(@product) %>')
$('#newProductFormModal').modal('hide');
$('#newProductForm')[0].reset();
<% end %>
需要注意一下上面使用了j 这个辅助方法,它会将我们产生的信息转移成js方法