简体   繁体   中英

Client Side Validations not working for second row in ASP.NET MVC

Model as below:

public class User
    {
        [DisplayName("ID")]
        [Range(0, 9999)]
        public int ID { get; set; }
public string Mask { get; set; }
}

And then controller returns IQueryable of above model

There are two views. Parent view and then partial view which renders each row from the Model

Main View

@model IQueryable<User>
@{
    var Array = Model.ToArray();

}
//Header here
            <tbody id="table-body-vlan">
                @{
                    for (var i = 0; i < Array.Length; i++)
                    {
                        Html.RenderPartial("_AddRow", Array [i], new ViewDataDictionary() { { "Index", i } });
                    }
                }
            </tbody>
        </table>
    </div>

    }

**And then partial view **

@model User
@{
    var index = ViewData["Index "];
}

<tr class="js-deletable-item" id="row-@index" data-id="@Model.ID" >

    <td class="editable">
        @Html.TextBoxFor(v => Model.ID, new {Name = "ID[" + index + "]", id = "id-" + Model.ID, Value = Model. ID > 0 ? Model. ID.ToString() : ""})
    </td>
    <td class="editable">
        @Html.TextBoxFor(v => Model.Name, new {Name = "Id[" + index + "].Name", data_val = "false" })
    </td>
</tr>

Issue as below: If there are 10 records in the IQueryable then client side validations applies only to first row.

eg if I type 101S for ID field in first row I gets the warning (By changing the background color) that invalid ID. But if I do same for second or other rows then I don't see background color change. Client side validations (defined through Data Annotations) are applying only for first row.

I guess after first row rendered it is not adding those Annotation related properties to the other rows.

I suggest you take a look at Editor and Display Templates in MVC:

Create an editor template here : ~/Views/Shared/EditorTemplates/User.cshtml like this:

@model User
<tr class="js-deletable-item">
    <td class="editable">
        @Html.TextBoxFor(m => m.Id)
    </td>
    <td class="editable">
        @Html.TextBoxFor(m => m.Name)
    </td>
</tr>

This will automatically be rendered for each element of your model whenever you call EditorForModel .

In your controller, do a .ToList() on your IQueryable<User>() object, before sending to the view.

In the Main View:

@model IEnumerable<User>

<table>
    <thead>
        <tr>
            <td>Id</td>
            <td>Name</td>
        </tr>
    </thead>
    <tbody>
        @Html.EditorForModel()
    </tbody>
</table>

Much simpler and cleaner right? But the main advantage of using these templates is, they will automatically create appropriate name attributes. Something like:

<input data-val="true" name="[0].Id" value="" />
<span class="text-danger field-validation-valid" data-valmsg-for="[0].ID"></span> 

Each row gets a unique name attribute. In your code, all your rows have the same name="ID" and data-valmsg-for="ID" . Because of this, only first row is getting validated.

The name attributes are also crucial when forms containing collections are being submitted. Otherwise, the User list will end being null when you submit ( Refer ).

If you don't want to use EditorTemplates , you'd have to do a for loop (not foreach ) and populate the rows.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM