如何使用 Devise 和 Hotwire 创建动态用户表单

问题描述 投票:0回答:1

我已在 Rails 7 应用程序中安装了身份验证系统。我希望能够使用 hotwire 为组织和个人用户类型创建动态表单。也就是说,当我单击单个选项时,应显示许多表单字段,而其他字段则隐藏。我应该能够在新注册页面和编辑注册页面上执行此操作。

由于我尝试使用热线来完成这项工作,所以我有一个导航刺激控制器

navigate_controller.js

import { Controller } from "@hotwired/stimulus";

/*
 * Usage
 * =====
 *
 * add data-controller="navigate" to the turbo frame you want to navigate
 *
 * Action (add to radio input):
 * data-action="change->navigate#to"
 * data-url="/new?input=yes"
 *
 */
export default class extends Controller {
  to(e) {
    e.preventDefault();

    const { url } = e.target.dataset;

    this.element.src = url;
  }
}

在我的注册页面中,我有一个条件语句,它包装了组织字段以及指向导航控制器的涡轮框架标签。

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <%= turbo_frame_tag "account_types", data: { controller: "navigate" } do %>

    <div class="form-check form-check-inline">
      <%= f.label :account_type, value: 'individual', class: 'form-check form-check-inline' do %>
        <%= f.radio_button :account_type, 'individual', class: 'form-check-input', data: { action: "change->navigate#to", url: new_account_registration_path({ account: { account_type: "individual" } }) } %>
        <label class="form-check-label">Individual</label>
      <% end %>

      <%= f.label :account_type, value: 'organization', class: 'form-check form-check-inline' do %>
        <%= f.radio_button :account_type, 'organization', class: 'form-check-input', data: { action: "change->navigate#to", url: new_account_registration_path({ account: { account_type: "company" } }) } %>
        <label class="form-check-label">Organization</label>
      <% end %>
    </div>

    <% if @account.organization? %>

      <div class="field">
        <%= f.label :organization_name %><br />
        <%= f.text_field :organization_name, autocomplete: "Organization name" %>
      </div>

      <div class="form-check form-check-inline">
        Organization Type
        <%= f.label :organization_type, value: 'base', class: 'form-check form-check-inline' do %>
          <%= f.radio_button :organization_type, 'base', class: 'form-check-input' %>
          <label class="form-check-label">Base</label>
        <% end %>

        <%= f.label :organization_type, value: 'ministry', class: 'form-check form-check-inline' do %>
          <%= f.radio_button :organization_type, 'ministry', class: 'form-check-input' %>
          <label class="form-check-label">Ministry</label>
        <% end %>
      </div>

    <% else %>
      <div class="field">
        <%= f.label :firstname %><br />
        <%= f.text_field :firstname, autocomplete: "firstname" %>
      </div>

      <div class="field">
        <%= f.label :surname %><br />
        <%= f.text_field :surname, autocomplete: "surname" %>
      </div>
    <% end %>
  <% end %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autocomplete: "email" %>
  </div>

  <div class="field">
    <%= f.label :username %><br />
    <%= f.text_field :username, autocomplete: "username" %>
  </div>

  <div class="field">
    <%= f.label :state %><br />
    <%= f.text_field :state, autocomplete: "state" %>
  </div>

  <div class="field">
    <%= f.label :country %><br />
    <%= f.text_field :country, autocomplete: "country" %>
  </div>

  <div class="field">
    <%= f.label :bio %><br />
    <%= f.text_area :bio, autocomplete: "bio" %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <br>

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

<%= render "devise/shared/links" %>

我还生成了设备注册控制器,将参数添加到新操作中

# frozen_string_literal: true

class Accounts::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]
  before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
  def new
    # super
    @account = Account.new configure_sign_up_params
  end

  # POST /resource
  # def create
  #   super
  # end

  # GET /resource/edit
  # def edit
  #   super
  # end

  # PUT /resource
  # def update
  #   super
  # end

  # DELETE /resource
  # def destroy
  #   super
  # end

  # GET /resource/cancel
  # Forces the session data which is usually expired after sign
  # in to be expired now. This is useful if the user wants to
  # cancel oauth signing in/up in the middle of the process,
  # removing all OAuth session data.
  # def cancel
  #   super
  # end

  protected

  # If you have extra params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :firstname, :surname, :state, :country, :bio, :account_type, :organization_name, :organization_type])
  rescue
    {}
  end

  # If you have extra params to permit, append them to the sanitizer.
  def configure_account_update_params
    devise_parameter_sanitizer.permit(:account_update, keys: [:username, :firstname, :surname, :state, :country, :bio, :account_type, :organization_name, :organization_type])
  end

  # The path used after sign up.
  # def after_sign_up_path_for(resource)
  #   super(resource)
  # end

  # The path used after sign up for inactive accounts.
  # def after_inactive_sign_up_path_for(resource)
  #   super(resource)
  # end
end

我想我没有正确自定义设备注册控制器,因此它无法工作

ruby-on-rails ruby hotwire-rails
1个回答
0
投票

configure_sign_up_params
仅添加额外的参数以允许,然后在相应的操作中uses

pp devise_parameter_sanitizer

#=>
<Devise::ParameterSanitizer:0x00007fd64171a420
 @auth_keys=[:email],
 @params=#<ActionController::Parameters {"controller"=>"accounts/registrations", "action"=>"new"} permitted: false>,
 @permitted=
  {:sign_in=>[:email, :password, :remember_me],
   :sign_up=>[:email, :password, :password_confirmation, :account_type],
   # ^ used in Devise::RegistrationsController#create action
   :account_update=>[:email, :password, :password_confirmation, :current_password]},
 @resource_name=:account>

sign_up_params
方法是您在注册时要用来获取允许的参数的方法:

class Accounts::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create, :new]

  def new
    build_resource sign_up_params
  end

  protected

  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:account_type])
  end
end

您确实必须查看设计源代码才能了解发生了什么。基本导轨也适用于这种情况:

class Accounts::RegistrationsController < Devise::RegistrationsController
  def new
    @account = Account.new(params.fetch(:account, {}).permit(:account_type))
  end
end

你也不必要地嵌套

<label>
标签:

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= turbo_frame_tag "account_types", data: {controller: "navigate"} do %>
    <%= f.label :account_type_individual do %>
      <%= f.radio_button :account_type, "individual",
        data: {
          action: "change->navigate#to",
          url: new_account_registration_path(account: {account_type: "individual"})
        }
      %>
      Individual
    <% end %>

    <%= f.label :account_type_organization do %>
      <%= f.radio_button :account_type, "organization",
        data: {
          action: "change->navigate#to",
          url: new_account_registration_path(account: {account_type: "organization"})
        }
      %>
      Organization
    <% end %>

    <% if resource.account_type == "organization" %>
      # TODO: company fields
    <% end %>
  <% end %>

  <%= f.submit "Sign up" %>
<% end %>
© www.soinside.com 2019 - 2024. All rights reserved.