MVC - 选择单选按钮时需要填写文本框

时间:2016-12-13 22:14:28

标签: asp.net-mvc razor

试图找出解决此问题的最佳方法。

我需要在需要的地方使用逻辑: 1)如果颜色类型允许金额,则为金额 2)信用卡(如果适用)(此时仅允许使用1种颜色)。

在视图中,我有所需的验证器,但由于它适用于金额,它显示所有金额,而不仅仅是所选单选按钮的文本框。

我已经尝试过jQuery在点击时在字段上放置必需属性但似乎在我设置它时它适用于每个项目:    示例:$('#TxtColorType_Green')。规则​​("添加","必需");

样本截图

Sample Screen Shot

以下示例演示了它的工作原理:

  1. 红色 - 允许金额,但没有信用卡
  2. 绿色 - 允许金额和信用卡
  3. 蓝色 - 不允许金额
  4. 模型

    public class ColorSelected
    {
        [Required(ErrorMessage = "Color Required")]
        [Display(Name = "Color Type:")]
        public string ColorTypeId { get; set; }
    
        // [Required(ErrorMessage = "Color Amount Required")]  since Radio Button, need to set Required attribute when selected **
        [Display(Name = "Color Amount:")]
        public decimal? CostAmt { get; set; }
    }
    
    public class ColorType
    {
        Public String ColorTypeId;
        Public String ColorTypeShortDesc;
        Public String Description;
        Public String AmountDescription;
        Public String DefaultChoice;
        public bool? DefaultChoice { get; set; }
        public bool? AllowCreditCard { get; set; }
    
        public ColorType()
        {
            init();
        }
    }
    
    public class ColorTypeRed : ColorType
    {
        public override void init()
        {
            ColorTypeId = "R";
            ColorTypeShortDesc = "Red";
            Description = "Red";
            AmountDescription = "Pay Later.";
            DefaultChoice = true;
        }
    }
    
    public class ColorTypeGreen : ColorType
    {
        public override void init()
        {
            ColorTypeId = "G";
            ColorTypeShortDesc = "Gr";
            Description = "Green";
            AmountDescription = "Pay Now";
            AllowCreditCard = true;    
        }
    }
    
    public class ColorTypeBlue : ColorType
    {
        public override void init()
        {
            ColorTypeId = "B";
            ColorTypeShortDesc = "Bl";
            Description = "Blue";
            AmountDescription = null;
        }
    }
    

    视图模型

            public class ColorViewModel
            {
                public ColorSelected colorSelected;
                public List<ColorType> ColorTypes;
                public ColorViewModel()
                {
                    ColorTypes.Add(new ColorTypeBlue());
                    ColorTypes.Add(new ColorTypeRed());
                    ColorTypes.Add(new ColorTypeGreen());
    
                }
            }
    

    查看

        @model ColorViewModel
        <div id="divColorType" class="ec-radiobtnlist">
            @{
                foreach (var ColorType in Model.ColorTypes)
                {
                    var idVal = string.Format("ColorType_{0}", ColorType.ColorTypeShortDesc);
                    <div>
                        <label>
                            @Html.RadioButtonFor(m => m.ColorSelected.ColorTypeId,
                                                ColorType.ColorTypeId,
                                                new { id = string.Format("Rb{0}", idVal) }
                                            )
                            <span>@ColorType.Description</span>
                        </label>
    
                        @{
                            if (ColorType.AmountDescription != null)
                            {
                                <text>
                                    @Html.TextBoxFor(m => m.ColorSelected.CostAmt,
                                            new { @id = string.Format("TxtAmt{0}", idVal), @class = "txtAmt", @maxlength = "10", @size = "3" }).00,
                                    @Html.Raw(ColorType.AmountDescription)
                                    @*@Html.ValidationMessageFor(m => m.ColorSelected.CostAmt)  Unfortunately right now if put this in the error will occur on ALL Color types as it uses the same property*@
                                </text>
                            };
                            if (ColorType.AllowCreditCard == true)
                            {
                                <div id=@string.Format("{0}_PmtCC", idVal)>
                                    @Html.Partial("_CreditCardDetails")
                                </div>
                            };
                        }
                </div>
                }
            }
        </div>
    

    提前致谢!

1 个答案:

答案 0 :(得分:1)

您的代码失败有多种原因,包括为同一属性生成多个文本框(CostAmt)和DefaultModelBinder只会绑定第一个值(因此,如果您选择&# 39;绿色&#39;,与&#39; Red&#39;相关联的文本框的值将被绑定)。实际上,POST方法中不会绑定任何内容,因为您的视图模型仅包含字段,而不包含属性。

要同时进行客户端和服务器端验证,您需要使用实现IClientValidatable的条件验证属性,例如应用于描述&#39的属性的foolproof [RequiredIf("SelectedColor", "G")] ; CreditCard&#39;,这些属性也必须在视图模型中。 AFAIK,没有任何开箱即用的处理“必需品”的服务。对于多个值(&#39;红色&#39;绿色&#39;),您可以从GitHub

下载我的RequiredIfContains属性

您的视图模型应为

public class ColorViewModel
{
    public string SelectedColor { get; set; } // set this to "R" or "G" or "B" initially to select a radio button
    public bool IsAmountHidden { get; set; } // set based on the value of SelectedColor
    public bool IsCreditCardHidden { get; set; }
    public List<ColorType> ColorTypes { get; set; }
    [RequiredIfContains("SelectedColor", "R, G")] // custom validation attribute
    public decimal? Amount { get; set; } // not clear why this is decimal when your view shows the fractions as .00
    [RequiredIf("SelectedColor", "G")]
    public string SelectedCreditCard { get; set; }
    ... more properties of Credit Card
    public IEnumerable<SelectListItem> CreditCardTypeList { get; set; }
}

然后在视图中

// Generate radio buttons
@foreach (var ColorType in Model.ColorTypes)
{
    <label>
        @Html.RadioButtonFor(m => m.SelectedColor, ColorType.ColorTypeId, new { id = "", @class = "color" })
       <span>@ColorType.Description</span>
    </label>
}
// Generate textbox
@{ var amountClass = Model.IsAmountHidden ? "hidden" : null; }
<div id="cost" class="@amountClass ">
    @Html.TextBoxFor(m => m.Amount)
    @Html.ValidationMessageFor(m => m.Amount)
</div>
// Generate credit card controls
@{ var creditCardClass = Model.IsCreditCardHidden ? "hidden" : null; }
<div id="creditcard" class="@creditCardClass">
    @Html.DropDownListFor(m => m.SelectedCreditCard, Model.CreditCardTypeList)
    @Html.ValidationMessageFor(m => m.SelectedCreditCard)
    .... // more properties of Credit Card
</div>

使用hidden

设置display: none;的样式

然后,您需要一些javascript来处理单选按钮.change()事件,以根据所选单选按钮的值切换控件的可见性

$('.color').change(function() {
    var selected = $('.color:checked').val();
    // add or remove the 'hidden' class name based on the value
});