我已在 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
我想我没有正确自定义设备注册控制器,因此它无法工作
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 %>