通過彈出層實現新建功能 ruby on rails
阿新 • • 發佈:2019-01-02
(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方法