【问题标题】:Assigning model instance attributes based on a checkbox value根据复选框值分配模型实例属性
【发布时间】:2023-03-30 14:17:01
【问题描述】:

我有一个具有stage_namereal_name 字符串属性的用户模型。我想做的是在我的_form.hmlt.erb 中的实名输入框旁边有一个复选框,询问,Real name is stage name?。如果选中,那么我想将真实姓名指定为舞台名称并禁用舞台名称input box withreal_name`真实姓名现在作为其值。到目前为止,我有:

_form.html.erb

<%= form_for @user do |f| %>
  <div>
    <%= f.text_field :stage_name %>
    <%= f.text_field :stage_name %> 
  </div>

  <div>
    <%= f.text_field :real_name %>
    <%= f.text_field :real_name %>

    # Not sure how to bind my model code to this checkbox
    <%= f.checkbox %>
    <%= f.label 'Real name is stage name?' %>
  </div>

  <div>
    <%= f.submit %>
  </div>
<% end %>

<script>
  $(function() {
    $("input[type='checkbox']").click(function() {
      var $checkbox   = $(this),
          $secondForm =  $("input[type='text']").eq(2);

      if ($checkbox.is(":checked")) {
        $secondForm.attr("disabled", true).val("<%= @user.real_name %>");
      } else {
          $secondForm.attr("disabled", false).val("");
      }
    });
  )};
</script>

【问题讨论】:

    标签: jquery ruby-on-rails forms checkbox input


    【解决方案1】:

    您需要做的就是在模型中分配一个属性访问器。

    attr_accessor :real_name_is_stage_name
    

    这将在您的模型中创建一个非持久属性,您可以在其中一个回调中检查该属性,如果值为 1,则设置 real_name = stage_name,例如:

    before_save do
      if real_name_is_stage_name == "1"
        real_name = stage_name
      end
    end
    

    然后将复选框设置为与您所做的更改进行交互,以便您可以将复选框的值发送给模型,如下所示:

    <%= f.check_box :real_name_is_stage_name %>
    

    如果你这样做了,在 javascript 代码中你只需要在选中 check_box 时禁用舞台名称 text_field,rails 将完成剩下的工作

    模型.rb

    class Model < ActiveRecord::Base
      attr_accessor :name_check
      ## Validation
      ## Callbacks
      before_validation do 
        if self.name_check == "1" and self.stage_name.present? and !self.real_name.present?
          self.real_name = self.stage_name
        end
      end
    end
    

    _form.html.erb

    <%= form_for @user do |f| %>
        <%= render 'shared/error_messages', object: @user %>
    
        <div>
            <%= f.label :stage_name %><br>
            <%= f.text_field :stage_name %>
        </div>
    
        <div>
            <%= f.label :real_name %><br>
            <%= f.text_field :real_name %>
            <div>
                <%= f.label :name_check, 'Real Name is Stage Name?' %>
                <%= f.check_box :name_check, value: f.obj.real_name.eql?(f.obj.stage_name)? "1" : "0" if f.obj.real_name.present? and f.obj.stage_name.present? %> %>
            </div>
        </div>
    
        <div>
            <%= f.label :origin %><br>
            <%= f.text_field :origin %>
        </div>
    
        <%= f.submit %>
    <% end %>
    
    <%= render 'scripts' %>
    

    _scripts.html.erb

    <script>
        $(function() {  
            var $nameCheck = $('#artist_name_check'),
                $stageName = $('#artist_stage_name'),
                $realName  = $('#artist_real_name'),
                $originalVal = $stageName.val();
    
            // Checks and mirrors artist's real name and stage name
    
            if ($nameCheck.is(':checked')) {
                $stageName.attr("readonly", "readonly");
            }
    
            $nameCheck.click(function() {
                if ($nameCheck.is(":checked")) {
                  $stageName.attr("readonly", "readonly").val($realName.val());
                } else {
                    $stageName.attr("readonly", false).val($originalVal).focus();
                }
            });
        });
    </script>
    

    【讨论】:

    • 如果您正在验证stage_name 的存在,则将您的代码添加到before_validation 块中,而不是before_save
    • :real_name_is_stage_name 的值没有保存。在我的控制器的 user_params 方法中添加了上面的代码以及允许的 :real_name_is_stage_name 但没有运气。
    • 该值不应该被保存它只是一个临时值,它会告诉你复选框是否被选中。您是否验证了stage_name 的存在。你能告诉我更新的型号代码吗?
    • 我想要做的是保存检查的值,以防用户想要编辑他们的页面,它会显示他们是否使用他们的真实/舞台名称。在等待您的回复时,我创建了一个可能的解决方案,导致创建了 name_check 布尔属性。我不得不问,创建物理数据库属性与虚拟属性是否可行?
    • 如果复选框的主要功能是匹配两个字段,您可以检查两个名称在您的视图中是否相等并将check_box值设置为"1"。作为概念证明,请考虑以下内容:&lt;%= f.check_box :real_name_is_stage_name, value= f.obj.real_name.eql?(f.obj.stage_name)? "1" : "0" if f.obj.real_name.present? and f.obj.stage_name.present? %&gt;
    【解决方案2】:

    设法创建了一个优雅的基于脚本的解决方案,不需要后端逻辑。需要注意的一件非常重要的事情是,对我的输入框使用disabled 属性会阻止数据被保存。相反,我使用readonly 并在未选中时将其设置为false。最重要的一点是确定如何使复选框保持选中/取消选中状态,尽管它不是模型的一部分。通过使用第一个条件,这一切都成为可能。

    总而言之,当文档加载脚本时,首先检查舞台名称的值是否等于真实姓名的值。如果是这样,则选中该复选框。一旦进入编辑视图,点击功能用于切换真实姓名输入值的状态。

    _form.html.erb

    <%= form_for @user do |f| %>
        <%= render 'shared/error_messages', object: @user %>
    
        <div>
            <%= f.label :stage_name %><br>
            <%= f.text_field :stage_name %>
        </div>
    
        <div>
            <%= f.label :real_name %><br>
            <%= f.text_field :real_name %>
            <div>
                <%= label_tag 'user_name_check', 'Real Name is Stage Name?' %>
                <%= check_box_tag 'user_name_check' %>
            </div>
        </div>
    
        <div>
            <%= f.label :origin %><br>
            <%= f.text_field :origin %>
        </div>
    
        <%= f.submit %>
    <% end %>
    
    <%= render 'scripts' %>
    

    _scripts.html.erb

    <script>
        $(function() {  
            var $nameCheck = $('#user_name_check'),
                $stageName = $('#user_stage_name'),
                $realName  = $('#user_real_name'),
                $originalVal = $stageName.val();
    
            // Checks and mirrors user's real name and stage name
    
            if ($realName.val() == $stageName.val() && $realName.val() != '') 
                $stageName.attr({
                  checked:  'checked',
                  readonly: 'readonly'
                });
            }
    
            $nameCheck.click(function() {
                if ($nameCheck.is(':checked')) {
                  $stageName.attr('readonly', 'readonly').val($realName.val());
                } else {
                    $stageName.attr('readonly', false).val($originalVal).focus();
                }
            });
        });
    </script>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 1970-01-01
      相关资源
      最近更新 更多