Search code examples
javascriptjqueryhtmlasp.net-mvcjquery-steps

JQuery parent selector to find step


I am using a jquery steps control. The form is posted in the onFinished() event with an Ajax request being fired off. From the server I return the following if any validation errors occur:

{
    "ErrorMessages": 
        [{
            "PropertyName":"Complainant.Address.StreetName",
            "ErrorMessage":"The complainant street name is required."
        },
        {
            "PropertyName":"Complainant.Address.Suburb",
            "ErrorMessage":"The complainant suburb is required."
        }]
}

Next in jQuery I find the appropriate span element (that is created with the ASP.NET MVC's @Html.ValidationMessageFor) and give it the provided validation message:

if (response.ErrorMessages != null) {
    for (var i = 0; i < response.ErrorMessages.length; i++) {
        var validationSpan = $("span[data-valmsg-for='" + response.ErrorMessages[i].PropertyName + "'");
        validationSpan.html(response.ErrorMessages[i].ErrorMessage);
        validationSpan.removeClass("field-validation-valid");
        validationSpan.addClass("field-validation-error");
    }
}

Next step is to set the Jquery step header as red in order to show that a validation error has occurred on that step. This part is not working:

var section = validationSpan.parent(".step-div");
$("#steps-uid-0-t-" + section.attr("step")).css("background", "#ff3111");

I have the following html structure:

<div>
    <h1>Complaint details</h1>
    <section>
        <div class="step-div" step="0">
            <div class="form-group">
                @Html.LabelFor(model => model.Complainant.Address.StreetName, new { @class = "col-md-3 control-label" })
                <div class="col-md-8">
                    @Html.TextBoxFor(model => model.Complainant.Address.StreetName, new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.Complainant.Address.StreetName)
                </div>
            </div>
        </div>
    </section>
<div>

The part that seems to not be working:

var section = validationSpan.parent(".step-div");

This should give me the <div> that's directly inside the <section>, but it doesn't seem to. If I log this section variable I get the following:

{ length: 0, prevObject: Object, context: HTMLDocument ? 134 }

enter image description here

The rendered <a> element that I want to apply the style to looks like this (depending on which step it is):

Step 1:

<a id="steps-uid-0-t-0" href="#steps-uid-0-h-0" aria-controls="steps-uid-0-p-0"><span class="number">1.</span> Complainant details</a>

Step 2:

<a id="steps-uid-0-t-1" href="#steps-uid-0-h-1" aria-controls="steps-uid-0-p-1"><span class="number">2.</span> Complaint details</a>

Solution

  • Try .parents() instead of .parent(). Better yet, try the .closest().

    .parents() gets all the ancestors that match the given selector.

    .parent() looks up only on the direct parent.

    .closest() looks up element itself and the ancestors to return the first one that matches the given selector.