سؤال

I am trying to fix a modelview's validation issue before submitting to the server

Here is the Main ViewModel

    public class AdmissionViewModel
    {
        public int OperatorID { get; set; }

/* some other members */

        public AdmissionFeeViewModel Fee { get; set; }

        public AdmissionFallDateViewModel FallAdmission { get; set; }

        public AdmissionDateViewModel SpringAdmission { get; set; }

        public AdmissionDateViewModel SummerAdmission { get; set; }


    }

Here are definations for the above ViewModel members

public class AdmissionFeeViewModel
{
    public AdmissionFeeBaseModel Domestic { get; set; }
    public AdmissionFeeBaseModel International { get; set; }
}

--> Base model

 public class AdmissionFeeBaseModel
    {
        public int? AdmissionFeeID { get; set; }

    [Required(ErrorMessage = "Application Fee is required")]
    public decimal? ApplicationFee { get; set; }

    public string ApplicationFeeWaiver { get; set; }

    public string FeeWaiverNotes { get; set; }

    public string FeeDataUrl { get; set; }
}


public class AdmissionFallDateViewModel
{
    public AdmissionFallDateBaseModel Domestic { get; set; }
    public AdmissionFallDateBaseModel International { get; set; }
}

--> base Model

public class AdmissionFallDateBaseModel: AdmissionDateBaseModel
{
    [Display(Name = "Early Decision Offered")]
    public override string PriorityDecisionOffered { get; set; }

    [Display(Name = "Early Decision Deadline")]
    public override string PriorityDecisionDeadline { get; set; }

    [Display(Name = "Early Decision Notification")]
    public override string PriorityDecisionNotificationDate { get; set; }

    [Display(Name = "Early Decision Deposit Deadline")]
    public override string PriorityDecisionDepositDeadline { get; set; }

    [Display(Name = "Financial Aid Application Deadline")]
    public override string PriorityFinancialAidAppDeadline { get; set; }

    [Display(Name = "Early Action Offered")]
    public string PriorityActionOffered { get; set; }

    [Display(Name = "Early Action Deadline")]
    public string PriorityActionDeadline { get; set; }

    [Display(Name = "Early Action Notification")]
    public string PriorityActionNotificationDate { get; set; }

    [Display(Name = "Early Decision  or Action Notes")]
    public override string PriorityAdmissionNotes { get; set; }

    [Display(Name = "Data URL")]
    public override string PriorityDataURL { get; set; }
}

public class AdmissionDateViewModel
{
    public AdmissionDateBaseModel Domestic { get; set; }
    public AdmissionDateBaseModel International { get; set; }
}

--> base model

public class AdmissionDateBaseModel
    {
        [HiddenInput]
        public int? AdmissionDateID { get; set; }

        [Display(Name = "Regular Admission Deadline")]
        public string ApplicationDeadline { get; set; }

        [Display(Name = "Regular Admission Notification")]
        public string AdmissionNotificationDate { get; set; }

        [Display(Name = "Regular Admission Deposit Deadline")]
        public string DepositDeadline { get; set; }

        [Display(Name = "Accept Offer of Admission")]
        public string AcceptOfferDeadline { get; set; }

        [Display(Name = "Waiting List Used")]
        public string WaitingListUsed { get; set; }

        [Display(Name = "Deferred Admission")]
        public string DeferAdmission { get; set; }

        [Display(Name = "Transfer Admission")]
        public string TransferAdmission { get; set; }

        [Display(Name = "Financial Aid Application Deadline")]
        public string FinancialAidAppDeadline { get; set; }

        [Display(Name = "Admission Notes")]
        public string AdmissionNotes { get; set; }

        [Display(Name = "Data URL")]
        public string DataURL { get; set; }

        [Display(Name = "Priority Decision Offered")]
        public virtual string PriorityDecisionOffered { get; set; }

        [Display(Name = "Priority Decision Deadline")]
        public virtual string PriorityDecisionDeadline { get; set; }

        [Display(Name = "Priority Decision Notification Date")]
        public virtual string PriorityDecisionNotificationDate { get; set; }

        [Display(Name = "Priority Decision Deposit Deadline")]
        public virtual string PriorityDecisionDepositDeadline { get; set; }
    [Display(Name = "Priority Financial Aid Application Deadline")]
    public virtual string PriorityFinancialAidAppDeadline { get; set; }

    [Display(Name = "Admission Notes")]
    public virtual string PriorityAdmissionNotes { get; set; }

    [Display(Name = "Data URL")]
    public virtual string PriorityDataURL { get; set; }
}

Here is the main View where Kendo().TabStrip is placed with 4 tabs one for each member from AdmissionViewModel

@model UniversityApp.ViewModels.AdmissionViewModel
@Html.HiddenFor(model => model.OperatorID)

<table>

<tr>
    <td>
    @(Html.Kendo().TabStrip()
    .Name("tabAdmission")
    .Events(events => events
        .Select("tabAdmissionOnSelect")
    )
    .Animation(false)

    .Items(items =>
    {
        items.Add().Text("Application Fees").Content(@<text>
        @Html.EditorFor(m => m.Fee)
        </text>).Selected(true);
        items.Add().Text("Fall Admission").Content(@<text>
        @Html.EditorFor(m => m.FallAdmission)
        </text>);
        items.Add().Text("Spring Admission").Content(@<text>
        @Html.EditorFor(m => m.SpringAdmission)
        </text>);
        items.Add().Text("Summer Admission").Content(@<text>
        @Html.EditorFor(m => m.SummerAdmission)
        </text>);
    })
)
    </td>
</tr>
</table>

-->here is child views the the kendo.tabstrip uses

@model UniversityApp.ViewModels.AdmissionFeeViewModel
@Html.HiddenFor(model => model.Domestic.AdmissionFeeID)
@Html.HiddenFor(model => model.International.AdmissionFeeID)
<table>
    <tr>
        <th></th>
        <th>Domestic Applicant</th>
        <th>International Applicant</th>
    </tr>
    <tr>
        <td><label>Application Fee</label></td>
        <td>
            @Html.EditorFor(model => model.Domestic.ApplicationFee)
            @Html.ValidationMessageFor(model => model.Domestic.ApplicationFee)
        </td>
        <td>
            @Html.EditorFor(model => model.International.ApplicationFee)
            @Html.ValidationMessageFor(model => model.International.ApplicationFee)
        </td>
    </tr>
    <tr>
        <td><label>Application Fee Waiver</label></td>
        <td>
            @Html.EditorFor(model => model.Domestic.ApplicationFeeWaiver)
            @Html.ValidationMessageFor(model => model.Domestic.ApplicationFeeWaiver)
        </td>
        <td>
            @Html.EditorFor(model => model.International.ApplicationFeeWaiver)
            @Html.ValidationMessageFor(model => model.International.ApplicationFeeWaiver)
        </td>
    </tr>
    <tr>
        <td></td>
        <td></td>
        <td><input type="button" btn-next-tab="true"  value="Next" /></td>
    </tr>

/* childview */

 @model UniversityApp.ViewModels.AdmissionDateViewModel
@Html.HiddenFor(model => model.Domestic.AdmissionDateID)
@Html.HiddenFor(model => model.International.AdmissionDateID)


<table>
    <tr>
        <th></th>
        <th>Domestic Applicant</th>
        <th>International Applicant</th>
    </tr>
    <tr>
        <td>@Html.LabelFor(model => model.Domestic.ApplicationDeadline)</td>
        <td>
            @Html.EditorFor(model => model.Domestic.ApplicationDeadline)
            @Html.ValidationMessageFor(model => model.Domestic.ApplicationDeadline)
        </td>
        <td>
            @Html.EditorFor(model => model.International.ApplicationDeadline)
            @Html.ValidationMessageFor(model => model.International.ApplicationDeadline)
        </td>
    </tr>
/* all other properties */
    <tr>
        <td><input type="button" btn-previous-tab="true" value="Previous" /></td>
        <td></td>
        <td><input type="button" btn-next-tab="true" value="Next" /></td>
    </tr>
</table>

in the same way we have 2 more child views.

Anyway, problem is: when i click on submit (save) button in the main view, all the required fields ring bells, but if i am on any other tabs that do not have required fields and hit submit, form is submitted with out client validation errors.

هل كانت مفيدة؟

المحلول

I also had the same issue and after investigation, jQuery Validate by default ignores anything that is :hidden http://jqueryvalidation.org/validate/#ignore

From https://api.jquery.com/hidden-selector/ :hidden is defined as

  • CSS display value of none.
  • Form elements with type="hidden".
  • Width and Height are set to 0.
  • Ancestor element is hidden

When a tab strip isn't selected then it is set to be display:none so Validate will ignore the inputs as its ancestor is :hidden (display: none).

The workaround that I used was to add this to the view

<script>
    $(document).ready(function() {
        $("form").data("validator").settings.ignore = "";
    });
</script>

It will now of course validate everything on the view including your hidden inputs, so may not be the correct approach but might help. You could always and some specificity to $("form").data("validator").settings.ignore = "input[type=hidden]"

The Kendo Validator doesn't suffer from the same issue http://demos.telerik.com/kendo-ui/validator/index but the user won't know it's errored if the tab isn't in view, so you will need some sort of summary or try to work out which tab has the error then select it.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top