如何让一组单选按钮接受NULL(未选中)?

时间:2021-01-20 15:07:12

I'm working on a Rails application where I have some a set of two radio buttons where users can click "yes" or "no". The MySQL DB column created by the ActiveRecord migration is a tinyint.

我正在开发一个Rails应用程序,其中有一组两个单选按钮,用户可以单击“是”或“否”。由ActiveRecord迁移创建的MySQL DB列是一个tinyint。

If the user doesn't click either radio button I want MySQL to store NULL. (The column allows NULL.) And when they come back to edit the data, neither button should be checked.

如果用户不单击任一单选按钮,我希望MySQL存储为空。(列允许NULL)。当他们回来编辑数据时,不应该检查任何按钮。

What's happening is that ActiveRecord is storing 0 and then when I come back the "No" button is checked.

现在发生的是ActiveRecord正在存储0,当我返回时,“No”按钮被选中。

Rails 2.3.5

Rails 2.3.5

Form code (I'm using Haml):

表格编号(我正在使用Haml):

        = f.radio_button( :model_attribute, true )
        Yes

        = f.radio_button( :model_attribute, false )
        No

(In retrospect it probably would have been better to use a single checkbox, but it would be difficult to change that now.)

(回想起来,使用一个复选框可能会更好,但现在很难改变这一点。)

7 个解决方案

#1


2  

This seems to defeat the idea of radio buttons (i.e., choose one out of a set). If it is important to track "no response", then would it be possible to add a third radio button for this option? If you don't want the user selecting a response and then re-selecting "no response", you can selectively choose to display the button on your form based on its current value.

这似乎颠覆了单选按钮的概念。,从一组中选择一个)。如果跟踪“无响应”很重要,那么是否可以为该选项添加第三个单选按钮?如果您不想让用户选择响应,然后重新选择“无响应”,您可以选择根据当前值在窗体上显示按钮。

#2


3  

I ran into a problem like this with ASP.NET MVC. Since null is essentially a third possible state, I added a third hidden radio button that is selected by default. When my response contained the "null" radio button response, I manually set it. I'm not sure if this is exactly what you are going for or not, but it worked quite well for my situation.

我在ASP中遇到了这样的问题。净MVC。由于null实质上是第三种可能的状态,所以我添加了第三个默认选择的隐藏单选按钮。当我的响应包含“空”单选按钮响应时,我手动设置它。我不确定这是否是你想要的,但它对我的情况很好。

#3


2  

Here's my take. I want the user to be able to unselect true/false and set the attribute to nil (Rails 4):

这是我的花。我希望用户能够取消选择true/false并将属性设置为nil (Rails 4):

form

形式

= f.radio_button :accepted, true
= f.radio_button :accepted, false
= f.radio_button :accepted, 'nil'

controller

控制器

def widget_params
  if params[:widget][:accepted] == 'nil'
    params[:widget][:accepted] = nil
  end
  params.require(:widget).permit(:accepted)
end

#4


1  

How about adding :default => null to the ActiveRecord migration for the column?

如何向列的ActiveRecord迁移添加:default => null ?

#5


1  

I just checked it myself and it just works as you want. Are you sure there's no code in your update action or your model that changes the attribute? If there's no radio selected in your form, the params hash will have no value for that attribute and the record will keep its previous value. Check you model for an attribute writer method or callback methods.

我自己检查了一下,就可以了。您确定更新操作或模型中没有更改属性的代码吗?如果表单中没有选择单选,params散列将没有该属性的值,记录将保持其先前的值。检查您的模型以获得属性编写器方法或回调方法。

#6


1  

Judging from your response to my comment that seems to be the behavior you want so this doesn't seem to be a UI problem but instead a problem with your model. It looks to me that calling YourModel.create() would create a DB entry with a 0 in the column.

从你对我的评论的反应来看,这似乎是你想要的行为,所以这似乎不是一个UI问题,而是你的模型的问题。在我看来,调用您的model .create()将创建一个DB条目,列中为0。

Possibly you could fix this by defaulting model attribute to nil in your constructor because it appears that ActiveRecord will default it to false for you.

你可以通过在你的构造函数中默认的模型属性为nil来解决这个问题,因为ActiveRecord会默认为false。

class YourModel
  def initialize
    self.model_attribute = nil
  end
end

However, if you really want 3 options Yes, Not or Not Set then you should probably just change model_attribute from a boolean to an "enum" where 0 means "Not Set", 1 means "Yes" and 2 means "No".

但是,如果您真的想要3个选项Yes, Not或Not Set,那么您应该将model_attribute从一个布尔值改为一个“enum”,其中0表示“Not Set”,1表示“Yes”,2表示“No”。

#7


1  

I have solved this today in the following (simplified) example. It's not perfect, but it seems to work for me :) There must be a simpler way to circumvent Rails not sending through the param for radio buttons that do not have a value selected...

我今天已经在下面的(简化的)示例中解决了这个问题。它并不完美,但它似乎对我有用:)必须有一种更简单的方法来绕过Rails,而不是通过param发送没有选择值的单选按钮……

In the controller:

控制器:

def create
  params[:post] = Post.deselect_radio_buttons(params[:post])
  @post = Post.new(params[:post])

  if @post.save
    redirect_to post_path(@post), notice: 'Post created'
  else
    render action: :new
  end
end

in the model:

在模型中:

# Define the fields that are used as radio buttons in the form.
RADIO_BUTTONS = [:field1, :field2]

def self.deselect_radio_buttons(params)
  RADIO_BUTTONS.each do |field|
    if params[field].blank?
      params[field] = nil
    end
  end

  return params
end

#1


2  

This seems to defeat the idea of radio buttons (i.e., choose one out of a set). If it is important to track "no response", then would it be possible to add a third radio button for this option? If you don't want the user selecting a response and then re-selecting "no response", you can selectively choose to display the button on your form based on its current value.

这似乎颠覆了单选按钮的概念。,从一组中选择一个)。如果跟踪“无响应”很重要,那么是否可以为该选项添加第三个单选按钮?如果您不想让用户选择响应,然后重新选择“无响应”,您可以选择根据当前值在窗体上显示按钮。

#2


3  

I ran into a problem like this with ASP.NET MVC. Since null is essentially a third possible state, I added a third hidden radio button that is selected by default. When my response contained the "null" radio button response, I manually set it. I'm not sure if this is exactly what you are going for or not, but it worked quite well for my situation.

我在ASP中遇到了这样的问题。净MVC。由于null实质上是第三种可能的状态,所以我添加了第三个默认选择的隐藏单选按钮。当我的响应包含“空”单选按钮响应时,我手动设置它。我不确定这是否是你想要的,但它对我的情况很好。

#3


2  

Here's my take. I want the user to be able to unselect true/false and set the attribute to nil (Rails 4):

这是我的花。我希望用户能够取消选择true/false并将属性设置为nil (Rails 4):

form

形式

= f.radio_button :accepted, true
= f.radio_button :accepted, false
= f.radio_button :accepted, 'nil'

controller

控制器

def widget_params
  if params[:widget][:accepted] == 'nil'
    params[:widget][:accepted] = nil
  end
  params.require(:widget).permit(:accepted)
end

#4


1  

How about adding :default => null to the ActiveRecord migration for the column?

如何向列的ActiveRecord迁移添加:default => null ?

#5


1  

I just checked it myself and it just works as you want. Are you sure there's no code in your update action or your model that changes the attribute? If there's no radio selected in your form, the params hash will have no value for that attribute and the record will keep its previous value. Check you model for an attribute writer method or callback methods.

我自己检查了一下,就可以了。您确定更新操作或模型中没有更改属性的代码吗?如果表单中没有选择单选,params散列将没有该属性的值,记录将保持其先前的值。检查您的模型以获得属性编写器方法或回调方法。

#6


1  

Judging from your response to my comment that seems to be the behavior you want so this doesn't seem to be a UI problem but instead a problem with your model. It looks to me that calling YourModel.create() would create a DB entry with a 0 in the column.

从你对我的评论的反应来看,这似乎是你想要的行为,所以这似乎不是一个UI问题,而是你的模型的问题。在我看来,调用您的model .create()将创建一个DB条目,列中为0。

Possibly you could fix this by defaulting model attribute to nil in your constructor because it appears that ActiveRecord will default it to false for you.

你可以通过在你的构造函数中默认的模型属性为nil来解决这个问题,因为ActiveRecord会默认为false。

class YourModel
  def initialize
    self.model_attribute = nil
  end
end

However, if you really want 3 options Yes, Not or Not Set then you should probably just change model_attribute from a boolean to an "enum" where 0 means "Not Set", 1 means "Yes" and 2 means "No".

但是,如果您真的想要3个选项Yes, Not或Not Set,那么您应该将model_attribute从一个布尔值改为一个“enum”,其中0表示“Not Set”,1表示“Yes”,2表示“No”。

#7


1  

I have solved this today in the following (simplified) example. It's not perfect, but it seems to work for me :) There must be a simpler way to circumvent Rails not sending through the param for radio buttons that do not have a value selected...

我今天已经在下面的(简化的)示例中解决了这个问题。它并不完美,但它似乎对我有用:)必须有一种更简单的方法来绕过Rails,而不是通过param发送没有选择值的单选按钮……

In the controller:

控制器:

def create
  params[:post] = Post.deselect_radio_buttons(params[:post])
  @post = Post.new(params[:post])

  if @post.save
    redirect_to post_path(@post), notice: 'Post created'
  else
    render action: :new
  end
end

in the model:

在模型中:

# Define the fields that are used as radio buttons in the form.
RADIO_BUTTONS = [:field1, :field2]

def self.deselect_radio_buttons(params)
  RADIO_BUTTONS.each do |field|
    if params[field].blank?
      params[field] = nil
    end
  end

  return params
end