通过弹出层实现新建功能 ruby on rails

 

(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

 1 <%- model_class = Product -%>
 2 <div class="page-header">
 3   <h1><%=t '.title', :default => model_class.model_name.human.pluralize.titleize %></h1>
 4 </div>
 5 <table class="table table-striped">
 6   <thead>
 7     <tr>
 8       <th><%= model_class.human_attribute_name(:id) %></th>
 9       <th><%= model_class.human_attribute_name(:name) %></th>
10       <th><%= model_class.human_attribute_name(:price) %></th>
11       <th><%= model_class.human_attribute_name(:description) %></th>
12       <th><%= model_class.human_attribute_name(:created_at) %></th>
13       <th><%=t '.actions', :default => t("helpers.actions") %></th>
14     </tr>
15   </thead>
16   <tbody id="productsTable">
17     <%= render @products %>
18   </tbody>
19 </table>
20 <%= link_to t('.new', :default => t("helpers.links.new")),
21             new_product_path,
22             :class => 'btn btn-primary',
23             data: {toggle: "modal", target: "#newProductFormModal"} %>
24 
25 <%= content_for :page_modal do %>
26   <div class="modal fade" id="newProductFormModal" role="dialog" aria-labelledby="myModalLabel"
27     aira-hidden="true">
28     <div class="modal-dialog">
29       <%= form_for @product, remote: true, :html => {:class => 'form-horizontal',
30         id: "newProductForm"} do |f| %>
31         <div class = "modal-content">
32           <div class="modal-header">
33             <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
34             <h4 class="modal-title">添加一个商品</h4>
35           </div>
36 
37           <div class="modal-body">
38             <%= render partial: "input", locals: {f: f} %>
39           </div>
40 
41           <div class="modal-footer">
42             <%= link_to t('.cancel', :default => t('helpers.links.cancel')), '#',
43               :class => 'btn btn-default', data: {dismiss: "modal"} %>
44               <%= f.submit nil, :class => 'btn btn-primary', :data => { :"disable-with" => "请稍等..."} %>
45           </div>
46         </div>
47       <% end %>
48     </div>
49   </div>
50  <div class="modal fade" id="editProductFormModal" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
51     <div class="modal-dialog">
52       <%= form_tag "", method: :put, remote: true, data: { type: "json" }, id: "editProductForm", class: "form" do %>
53         <div class="modal-content">
54           <div class="modal-header">
55             <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
56             <h4 class="modal-title">编辑一个商品</h4>
57           </div>
58           <div class="modal-body">
59             <div class="alert alert-dismissible alert-danger" id="alert-content">
60               <button type="button" class="close" data-dismiss="alert">×</button>
61               <div id="msg"></div>
62             </div>
63             <div class="form-group">
64               <%= label_tag "product[name]", Product.human_attribute_name("name"), :class => 'control-label' %>
65               <%= text_field_tag "product[name]", "", :class => 'form-control', id: "editProductName" %>
66             </div>
67             <div class="form-group">
68               <%= label_tag "product[description]", Product.human_attribute_name("description"), :class => 'control-label' %>
69               <%= text_field_tag "product[description]", "", :class => 'form-control', id: "editProductDescription" %>
70             </div>
71             <div class="form-group">
72               <%= label_tag "product[price]", Product.human_attribute_name("price"), :class => 'control-label' %>
73               <%= text_field_tag "product[price]", "", :class => 'form-control', id: "editProductPrice" %>
74             </div>
75           </div>
76           <div class="modal-footer">
77             <%= link_to t('.cancel', :default => t("helpers.links.cancel")), '#', :class => 'btn btn-default', data: {dismiss: "modal"} %>
78             <%= submit_tag t('.confirm', :default => t("helpers.links.confirm")), :class => 'btn btn-primary', :data => { :"disable-with" => "请稍等..
79           </div>
80         </div>
81       <% end %>
82     </div>
83   </div>
84 
85 <% end %>
86 
87 <%= content_for :page_javascript do %>
88   <script>
89     $('#newProductFormModal').modal({
90       show: false,
91     })
92     $('#editProductFormModal').modal({
93       show: false,
94     })
95   </script>
96 <% 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 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

  def edit
    respond_to do |format|
      format.html
      format.json {render json: @product, status: :ok, location: @product }
    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方法

 

posted @ 2015-10-27 17:49  冰凌花花~  阅读(269)  评论(0编辑  收藏  举报