Ruby 于 Rails:使用 bootstrap 模态制作注册表单的最佳方法是什么?

Ruby on Rails: What is the best way to make a registration form using a bootstrap modal?

我正在尝试使用 bootstrap 模式弹出窗口为 Rails 应用程序上的 Ruby 创建注册表单。我自己从头开始对表单进行硬编码(没有使用 SimpleForm 或 Devise)。当我点击提交时,我似乎无法让数据通过。

这里是 users_controller.rb:

class UsersController < ApplicationController

#before_action :confirm_logged_in   
respond_to :html, :js

def index
 @users = User.all.sorted
end

def show
 @user = User.find(params[:id])
end

def new
 @user = User.new
end

def create
 @user = User.new(user_params)
 respond_to do |format|
  format.html { redirect_back }
  format.js
 end
 if @user.save
  flash[:success] = 'Welcome, #{@user.first_name}!'
 else
  render('new')
 end
end

def edit
 @user = User.find(params[:id])
end

def update
 @user = User.find(params[:id])
  if @user.update_attributes(user_params)
    flash[:success] = 'You have been updated.'
    redirect_to(:action => 'show')
  else
    render('edit')
  end
end

def delete
 @user = User.find(params[:id])
end

def destroy
 @user = User.find(params[:id]).destroy
 flash[:notice] = '#{@user.first_name} #{@user.last_name} has been deleted.'
 redirect_to ('home')
end

private

def user_params
 params.require(:user).permit(:first_name, :last_name, :email, :password, :confirm_password, :avatar)
end

end

这里是放置模态框的view/layouts/application.html.erb:

<button id="signupButton" data-toggle="modal", data-target="#registerModal">
        <span class="glyphicon glyphicon-user"></span>
        <%= link_to 'Register', new_user_path, remote: true %>
        </button>
      <div class="modal fade" id="registerModal" tabindex="-1" role="dialog" aria-labelledby="registerModalTitle" aria-hidden="true">

 <div class="modal-dialog">

    <div class="modal-content">

              <!-- REGISTER FORM -->

        <%= render 'users/register' %>

                <!-- END REGISTER FORM -->

    </div>

   </div>

</div>

</nav>
<!-- END NAVBAR --> 

最后是表格 partial (_register.html.erb):

<div class="modal-body">
 <%= form_for :user, remote: true do |f| %>

 <div class="form-group has-success has-feedback">
    <%= f.label :first_name, class: "sr-only" %>
    <%= f.text_field(:first_name, class: "form-control", placeholder: "First Name") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
</div>

<div class="form-group has-success has-feedback">
    <%= f.label :last_name, class: "sr-only" %>                  
    <%= f.text_field(:last_name, class: "form-control", placeholder: "Last Name") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
</div>

  <div class="form-group has-success has-feedback">
    <%= f.label :email, class: "sr-only" %>
    <%= f.text_field(:email, class: "form-control", placeholder: "Email") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
</div>

  <div class="form-group has-success has-feedback">
    <%= f.label :password, class: "sr-only" %>
    <%= f.password_field(:password, type: "password", class: "form-control", placeholder: "Password") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
  </div>

  <div class="form-group has-success has-feedback">
    <%= f.label :password, class: "sr-only" %>
    <%= f.password_field(:password, type: "password", class: "form-control", placeholder: "Confirm Password") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
</div>  

<div class="modal-footer">

  <%= link_to 'Close', "#", class: "btn btn-default", data: {dismiss: "modal"} %>
  <%= f.submit 'Register', class: 'btn btn-primary' %>

    </div>
  <% end %> 
</div>

这是我的 routes.rb 文件:

 Rails.application.routes.draw do

 get '/users', to: 'users#index'

 root 'access#index', as: '/'

 get '/home', to: 'home#home'

 #match ':controller(/:action(/:id))', :via => [:get, :post]

 resources :users

 resources :sessions

end

这是我的 user.rb 模型:

class User < ActiveRecord::Base

has_secure_password




before_save { self.email = email.downcase }

validates :first_name, :presence => true,
                        :length => { :maximum => 25 }
validates :last_name, :presence => true,
                        :length => { :maximum => 50 }
VALID_EMAIL_REGEX = /\A[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}\Z/i
validates :email, :presence => true,
                    :uniqueness => { case_sensitive: false}, 
                    :length => { :maximum => 100 },
                    :format => { with: VALID_EMAIL_REGEX },
                    :confirmation => true
validates :password, :presence => true,
                    :length => { :within => 6..20 }
validates_confirmation_of :password
#mount_uploader :picture, PictureUploader
#validate :picture_size
validates :avatar, :attachment_presence => true
validates_with AttachmentPresenceValidator, :attributes => :avatar
validates_with AttachmentSizeValidator, :attributes => :avatar, :less_than => 1.megabytes

scope :sorted, lambda { order("last_name ASC, first_name ASC") }

def name
 "#{first_name} #{last_name}"
end

private

   def picture_size
    if picture.size > 5.megabytes
    errors.add(:picture, " must be less than 5MB")
   end
end

end

这就是您通过 ajax 加载表单并将其注入 bootstrap modal 的方式。请注意,这是基于 scaffolded rails app - 您需要根据自己的应用进行调整。

1。设置页面特定 javascript

更改 views/application/layout.html.erb

中的 body 标签
<body data-controller="<%= controller_name %>" data-action="<%= action_name %>">

然后我们在 assets/javascripts/application.js 中设置一个侦听器,它告诉我们哪个页面已加载。

// This lets us bind "page specific javascript" by listening for the controller:action:loaded event.
$(document).on('page:change', function(){
    var data = $('body').data();
    var key = data['controller'] + ':' + data['action'] + ':loaded';
    console.log('Triggering', key);
    $(this).trigger(key);
});

这样我们就可以在主页上显示模式。如果您的模态不是“启动画面”,请随意跳过此步骤。

在我的示例中,我将 pages#home 作为根路径。

2。创建模态模板

views/layouts/_modal.html.erb 中创建通用模态模板。

<div class="modal fade" id="modal-template" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="exampleModalLabel">Generic Modal Title</h4>
      </div>
      <div class="modal-body">
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>

在您的 views/layouts/application.html.erb 中包含部分内容。

    <!-- ... -->
    </div> <!-- /container -->
    <%= render partial: 'layouts/modal' %>
  </body>
</html>

3。创建注册表单。

首先创建一个用户表单部分views/users/_form.html.erb

<%= form_for(@user) do |f| %>
  <% if @user.errors.any? %>
    <div id="form-errors">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% @user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="form-inputs">

    <div class="form-group has-success has-feedback">
      <%= f.label :first_name, class: "sr-only" %>
      <%= f.text_field(:first_name, class: "form-control", placeholder: "First Name") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
    </div>

    <div class="form-group has-success has-feedback">
      <%= f.label :last_name, class: "sr-only" %>
      <%= f.text_field(:last_name, class: "form-control", placeholder: "Last Name") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
    </div>

    <div class="form-group has-success has-feedback">
      <%= f.label :email, class: "sr-only" %>
      <%= f.text_field(:email, class: "form-control", placeholder: "Email") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
    </div>

    <div class="form-group has-success has-feedback">
      <%= f.label :password, class: "sr-only" %>
      <%= f.password_field(:password, type: "password", class: "form-control", placeholder: "Password") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
    </div>

    <div class="form-group has-success has-feedback">
      <%= f.label :confirm_password, class: "sr-only" %>
      <%= f.password_field(:confirm_password, type: "password", class: "form-control", placeholder: "Confirm Password") %>
      <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
    </div>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

然后将表格添加到您的 views/users/new.html.erb

<h1>New User</h1>

<%= render 'form' %>

<%= link_to 'Back', users_path %>

4。使用 Ajax.

加载表单

这看起来很复杂,但实际上并非如此。我们复制我们添加到页面的模态模板,并从我们使用 ajax.

加载的表单中注入组件
$(document).ready(function(){
    // Only fire this on the home page.
    // Replace this with a regular click handler if you do not want a "splash"
    $(document).on('pages:home:loaded', function(){
        // Load the page content from "/users/new"
        var promise = $.get("/users/new");
        // When the ajax request has finished
        promise.success(function(data){
            var $frag = document.createDocumentFragment(), // Good for performance
                $modal = $($('#modal-template')[0].outerHTML, $frag),
                $form = $($(data).find('#new_user')[0].outerHTML),
                $btn = $form.find('input[type="submit"]');
            // Wrap the modal content in the form.
            // Give the modal a unique ID.
            $modal.attr('id', 'register-modal');
            // Add the inputs from the form inside the body
            $modal.find('.modal-body').append($form);
            // Customize the title
            $modal.find('.modal-title').text('Sign Up!');
            // Add the submit button next to the close button
            $btn.addClass('btn btn-primary');
            // since the button is not actually in the form we add an event handler to submit the form.
            $btn.click(function(){
                $modal.find('form').submit();
            });
            $modal.find('.modal-footer').append($btn);
            // Attach the modal to document
            $('body').append($modal);
            // Open the modal
            $modal.modal({});
        });
        promise.fail(function(jqXHR, textStatus, errorThrown){
            console.error('Failed to fetch user registration form', textStatus, jqXHR, errorThrown);
        });
    });
});