Click event not working in Blazor while using JQuery Datatable - asp.net-core

I have initialized Datatable in OnAfterRenderAsync and it's working fine
but onclick event doesn't work.
Grid.razor
<tbody>
#foreach (RecommendedActivityCreateViewModel model in activityList)
{
<tr>
<td><img src="#model.image_url" width="100" /></td>
<td>#model.title</td>
<td>#model.description</td>
<td>#model.created_at.ToString("dd-MMM-yyyy")</td>
<td nowrap="nowrap">
<button #onclick="(()=>EditData(model.Id))" data-toggle="modal" data-target="#AddEditEmpModal" class="btn btn-sm btn-clean btn-icon" title="Edit details">
<i class="la la-edit"></i>
</button>
<a class="btn btn-sm btn-clean btn-icon delete-link" data-url="api/RecommendedActivity/" data-id="#model.Id" title="Delete">
<i class="la la-trash"></i>
</a>
</td>
</tr>
}
</tbody>
GridModel.cs
public class GridModel : ComponentBase
{
[Inject]
protected HttpClient Http { get; set; }
protected async Task EditData(string id)
{
await Http.GetAsync($"api/RecommendedActivity/{id}");
}
}

While you say "I have initialized Datatable in OnAfterRenderAsync" the example below does that and if you copy, paste and run it you'll find nothing gets rendered. You've fetched the data after you've rendered the page. Get the data in OnInitializedAsync and it works.
You also say "and it's working fine but onclick event doesn't work." The EditData method should be in Grid.razor not GridModel which is where it appears to be in the code snippets provided.
The code below shows a simple working example (with GetData in OnInitializedAsync).
#page "/Test"
#foreach (var country in Countries)
{
<div>#country.Country <button class="btn-btn-dark" #onclick="() => OnClick(country.Id)">Edit</button></div>
}
#code {
class Model
{
public int Id { get; set; }
public string Country { get; set; }
}
private List<Model> Countries = new List<Model>();
protected Task OnClick(int id)
{
var x = id;
return Task.CompletedTask;
}
protected override Task OnInitializedAsync()
{
// GetData();
return base.OnInitializedAsync();
}
protected override Task OnAfterRenderAsync(bool firstRender)
{
GetData();
return base.OnAfterRenderAsync(firstRender);
}
protected void GetData()
{
Countries = new List<Model>()
{
new Model(){ Id=1, Country = "UK"},
new Model(){ Id=2, Country = "Spain"},
new Model(){ Id=3, Country = "Portugal"}
};
}
}

Related

How to remove only images which are removed from webpage using Javascript

In ASP.Net Core MVC. I have created one product CREAT page which allows users to create product and upload multiple images of that product.
Now in editing page of this product I display all these pictures in <div> tag, with javascript of delete function to delete the picture which user want to remove and save the product details again.
From this point I don't understand how to tell ProductController.cs that which images should be deleted from database and which shouldn't.
Can someone put me on right direction, how exactly this process should work?
You can fire jquery call at each image delete; works for smaller set of images
You can store the deleted image-ids in an array and serialize the array to an hidden field and pass the array when you make one jquery call to ProductController.cs on edit submit.
You can check this repository for the solution
https://github.com/rajdeepdebnath/aspnetcore-mvc-collection
My view
#model List<WebApplication4.Controllers.Product>
#{
ViewData["Title"] = "Home Page";
}
#using (Html.BeginForm("Edit", "Home", FormMethod.Post))
{
if (Model != null)
{
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Desc</th>
<th>Images</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count; i++)
{
var product = Model[i];
var id = $"product[{i}].Id";
var name = $"product[{i}].Name";
var description = $"product[{i}].Description";
<tr>
<td>#product.Id<input type="hidden" value="#product.Id" name='#id' /></td>
<td><input type="text" value="#product.Name" name='#name' /></td>
<td><input type="text" value="#product.Description" name='#description' /></td>
<td>
#foreach (var image in product.ImageIdArr)
{
<span class="image" data-imageid="#image" style="display:inline-block;width:20px;height:20px;background-color:darkseagreen;">😊</span>
}
</td>
</tr>
}
</tbody>
</table>
<input type="hidden" value="[]" name="DeleteImageIdArr" id="DeleteImageIdArr" />
<input type="submit" value="submit" />
}
}
#section Scripts{
<script>
$(document).ready(function () {
$('.image').click(function (v) {
console.log(v);
console.log(v.target.dataset.imageid);
var arr = [];
arr = JSON.parse($('#DeleteImageIdArr').val());
console.log(Array.isArray(arr));
if (arr.indexOf(v.target.dataset.imageid) < 0) {
arr.push(v.target.dataset.imageid);
}
$('#DeleteImageIdArr').val(JSON.stringify(arr))
console.log($('#DeleteImageIdArr').val());
console.log(v.target.hidden);
v.target.hidden = true;
});
$.ajax();
});
</script>
}
My controller
public class HomeController : Controller
{
public IActionResult Index()
{
var products = GetProducts();
return View(products);
}
[HttpPost]
public IActionResult Edit(List<Product> product, string[] DeleteImageIdArr)
{
var products = GetProducts();
return View("Index", products);
}
public List<Product> GetProducts()
{
var products = new List<Product> {
new Product{ Id=1, Name="Test 1", Description="Test 1", ImageIdArr=new int[]{ 1,2,3 } },
new Product{ Id=1, Name="Test 2", Description="Test 2", ImageIdArr=new int[]{ 4,5,6 } },
new Product{ Id=1, Name="Test 3", Description="Test 3", ImageIdArr=new int[]{ 7,8,9 } },
};
return products;
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int[] ImageIdArr { get; set; }
}

Session problem.Why "Continue shopping" does not work?

I have this view with some product list. List from different table
<form method="get">
<td class="button13"><button type="submit" asp-action="Buy" asp-route-id="#p.ProductId" asp-controller="Search">Buy</button></td>
<input type="hidden" name="returnUrl" value="#ViewContext.HttpContext.Request.PathAndQuery()" />
</form>
Then we go to form post to add some information about client. And then we will go to cart
Controller
public ViewResult Index(string returnUrl)
{
return View(new CartIndexViewModel
{
Cart = GetCart(),
ReturnUrl = returnUrl
});
}
public ActionResult AddToCart(string returnUrl,int priceCart,DateTime dateFromCart, int Tick,int Fli)
{//we are here after form post
Cart cart = GetCart();
cart.AddItem(1,priceCart,dateFromCart);
SaveCart(cart);
return RedirectToAction("Index", new { returnUrl });
}
private Cart GetCart()
{
Cart cart = HttpContext.Session.GetJson<Cart>("Cart") ?? new Cart();
return cart;
}
private void SaveCart(Cart cart)
{
HttpContext.Session.SetJson("Cart", cart);
}
Second View
#model Phone1.Models.ViewModels.CartIndexViewModel;
<h2>Your cart</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Quantity</th>
<th>Item</th>
<th class="text-right">Price</th>
<th class="text-right">Subtotal</th>
</tr>
</thead>
<tbody>
#foreach (var line in Model.Cart.Lines)
{
<tr>
<td class="text-center">#line.Quantity</td>
<td class="text-left">#line.PriceCart</td>
<td class="text-left">#line.DateFromCart.ToString("D")"</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="3" class="text-right">Total:</td>
<td class="text-right">
#Model.Cart.ComputeTotalValue().ToString("c")
</td>
</tr>
</tfoot>
</table>
<div class="text-center">
<a class="btn btn-primary" href="#Model.ReturnUrl"><h3>Continue shopping</h3></a>
</div>
And Infrastructure files
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
namespace Phone1.Infrastructure
{
public static class SessionExtensions
{
public static void SetJson(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetJson<T>(this ISession session, string key)
{
var sessionData = session.GetString(key);
return sessionData == null
? default(T) : JsonConvert.DeserializeObject<T>(sessionData);
}
}
}
And other Infrasructure`s file
using Microsoft.AspNetCore.Http;
namespace Phone1.Infrastructure
{
public static class UrlExtensions
{
public static string PathAndQuery(this HttpRequest request) =>
request.QueryString.HasValue
? $"{request.Path}{request.QueryString}"
: request.Path.ToString();
}
}
Startup
public class Startup
{
public Startup(IConfiguration configuration) =>
Configuration = configuration;
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<PhoneAppDbContext>(options =>
options.UseSqlServer(Configuration["Data:PhoneAppDb:ConnectionString"]));
services.AddMvc();
services.AddMemoryCache();
services.AddSession();
services.AddControllersWithViews(mvcOtions =>
{
mvcOtions.EnableEndpointRouting = false;
});
services.AddMvc()
.AddRazorRuntimeCompilation();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStatusCodePages();
app.UseStaticFiles();
app.UseSession();
app.UseMvc(routes => {
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "",
template: "{controller=SearchTicket}/{action=AddToCart}/{id?}");
routes.MapRoute(
name: "",
template: "{controller=SearchTicket}/{action=Index}/{id?}");
});
}
}
}
Model 1
namespace Phone1.Models.ViewModels
{
public class CartIndexViewModel
{
public Cart Cart { get; set; }
public string ReturnUrl { get; set; }
}
}
Model 2
using System;
using System.Collections.Generic;
using System.Linq;
namespace Phone1.Models
{
public class Cart
{
private List<CartLine> lineCollection = new List<CartLine>();
public virtual void AddItem(int quantity,int priceCart,DateTime dateFromCart)
{
CartLine line = lineCollection
.FirstOrDefault();
if (line == null)
{
lineCollection.Add(new CartLine
{
DateFromCart=dateFromCart,
PriceCart=priceCart,
Quantity = quantity
});
}
else
{
//line.Quantity += quantity;
}
}
public virtual void RemoveLine(int priceCart,DateTime dateFromCart) =>
lineCollection.RemoveAll();
public virtual int ComputeTotalValue() =>
lineCollection.Sum(e => e.PriceCart);
//* e.Quantity
public virtual void Clear() => lineCollection.Clear();
public virtual IEnumerable<CartLine> Lines => lineCollection;
}
public class CartLine
{
public int CartLineId { get; set; }
public DateTime DateFromCart { get; set; }
public int PriceCart { get; set; }
public int Quantity { get; set; }
}
}
All things add to cart, but <a class="btn btn-primary" href="#Model.ReturnUrl"><h3>Continue shopping</h3></a> does not work at all.It does not work even like link <a>.What is wrong?
There is no error message.
Controller
public ViewResult Index(string returnUrl)
{
return View(new CartIndexViewModel
{
Cart = GetCart(),
ReturnUrl = returnUrl
});
}
public ActionResult AddToCart(string returnUrl,int priceCart,DateTime dateFromCart, int Tick,int Fli)
{//we are here after form post
Cart cart = GetCart();
cart.AddItem(1,priceCart,dateFromCart);
SaveCart(cart);
return RedirectToAction("Index", new { returnUrl });
}
We go to Index method with returnUrl

Link in partial Razor Page fires wrong OnGet

I am using a razor page to display an ItemT model and at the bottom I inserted a partial view to show all properties (which are not assigned to this model in a n:m relation).
The PageModel 'FreePropertiesToItemT' has two public properties:
public ItemT ItemT { get; set; } // the one Item to show
public IList<PropertyIndexViewModel> FreeProperties { get; set; } // all free properties
An OnGetAsync(int? id) Method is called which works fine. The Page shows all data correctly.
The view displays a link for every Property:
<a asp-page-handler="addProperty" asp-route-id="#item.PropertyID">add</a>
This creates the link:
add
This is the correct link (I think). The route, id value and the handler are correct because there is a second OnGet Method in the PageModel:
public async Task<IActionResult> OnGetaddPropertyAsync(int? id)
However, the link only calls OnGetAsync (and not OnGetaddProppertyAsync) every time and, of course, for every Property!
What am I missing?
Model of ItemT:
public class ItemT
{
[Key]
public int ItemTID { get; set; }
[Required]
[StringLength(100, MinimumLength = 1)]
[Display(Name = "ItemT")]
public string Title { get; set; }
public bool isActive { get; set; } = true;
public virtual ICollection<ItemTProperty> ItemTProperties { get; set; }
}
ViewModel of free properties:
public class PropertyIndexViewModel
{
[Key]
public int PropertyID { get; set; }
[Required]
[StringLength(100, MinimumLength = 1)]
public string Title { get; set; }
public bool DefaultsOnly { get; set; }
[Display(Name = "Unit")]
public string Unit { get; set; }
[Display(Name = "Valuetype")]
public string Valuetype { get; set; }
}
The Page to list one ItemT:
#page
#model Inventory.Areas.Inventory.Pages.ItemTs.FreePropertiesToItemTModel
#{
ViewData["Title"] = "FreePropertiesToItemT";
}
<h1>Free Properties</h1>
<div>
<h4>ItemT</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.ItemT.Title)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.ItemT.Title)
</dd>
<dt class="col-sm-2">
#Html.DisplayNameFor(model => model.ItemT.isActive)
</dt>
<dd class="col-sm-10">
#Html.DisplayFor(model => model.ItemT.isActive)
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="#Model.ItemT.ItemTID">Edit</a> |
<a asp-page="./Index">Back to List</a>
</div>
<p></p>
<div>
#{
ViewData["FreeProperties"] = true;
}
<partial name="../Properties/_Properties.cshtml" model="Model.FreeProperties" />
</div>
The Partial which is loaded:
#using Inventory.DAL.ViewModels
#model IList<PropertyIndexViewModel>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model[0].Title)
</th>
<th>
#Html.DisplayNameFor(model => model[0].DefaultsOnly)
</th>
<th>
#Html.DisplayNameFor(model => model[0].Unit)
</th>
<th>
#Html.DisplayNameFor(model => model[0].Valuetype)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.DefaultsOnly)
</td>
<td>
#Html.DisplayFor(modelItem => item.Unit)
</td>
<td>
#Html.DisplayFor(modelItem => item.Valuetype)
</td>
<td>
#if (ViewBag.FreeProperties != null)
{
<a asp-page-handler="addProperty" asp-route-id="#item.PropertyID">add</a>
}
</td>
</tr>
}
</tbody>
</table>
And the c# code behind the page:
namespace Inventory.Areas.Inventory.Pages.ItemTs
{
public class FreePropertiesToItemTModel : PageModel
{
private readonly IUnitOfWork _uow;
public FreePropertiesToItemTModel(IUnitOfWork uow)
{
_uow = uow;
}
public ItemT ItemT { get; set; }
public IList<PropertyIndexViewModel> FreeProperties { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
ItemT = await _uow.ItemTRepo.getById((int)id);
if (ItemT == null)
{
return NotFound();
}
FreeProperties = await _uow.PropertyRepo.getFreePropertiesForItemT((int)id);
return Page();
}
public async Task<IActionResult> OnGetaddPropertyAsync(int? id)
{
if( id == null)
{
return NotFound();
}
if(ItemT == null) { return NotFound(); }
await _uow.ItemTRepo.addProperty(ItemT.ItemTID, (int)id);
await _uow.Commit();
return Page();
}
}
}
The issue is that your handler name error ,change it like below:
public async Task<IActionResult> OnGetAddPropertyAsync(int? id)
The first letter of handler name must be capitalized , otherwise handler=addProperty in the url is treated as a query-string parameter not a handler name.

Update kendo grid columns without page reload in ASP MVC

I have a kendo grid where user can select list of columns from grid and save the selection by giving name (i.e view name). Each saved selection (view name) will show up as drop-down above grid so that user can change grid columns whenever they want. In current implementation, whenever user selects view name from one drop-down value to other, i call action method to select that view name as current view name. Then page reloads to invoke Index' action method to retrieve current view names columns values. I am using visible attribute in grid to show and hide columns in grid.
Now i was wondering if i can update the grid columns without reloading the page when user change the view name from the dropdown.
Thanks
Sanjeev
Screenshot:
Here is my setup:
ViewModel:
namespace MvcApplicatioin.Models
{
public class EmployeeViewModel
{
public EmployeeColumns EmployeeColumns { get; set; }
public IEnumerable<SelectListItem> EmployeeViewNames { get; set; }
public long EmployeeSelectedViewId { get; set; }
}
public class EmployeeResponse
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class EmployeeColumns
{
public bool Id { get; set; }
public bool FirstName { get; set; }
public bool LastName { get; set; }
}
}
Controller:
public class EmployeeController : Controller
{
// GET: Employee
public ActionResult Index()
{
var service = new EmployeeService();
EmployeeViewModel model = new EmployeeViewModel();
long currentViewId;
//setup views and column preferences
EmployeeColumns employeeColumns = service.GetCurrentEmployeeColumnsPreferences();
model.EmployeeColumns = employeeColumns;
model.EmployeeViewNames = service.GetAllEmployeeViewNames(out currentViewId);
model.EmployeeSelectedViewId = currentViewId;
return View(model);
}
}
Razor:
#using Kendo.Mvc.UI
#{
ViewBag.Title = "Employee Info:";
}
<h3 style="margin-bottom: 10px;">Employee Info</h3>
<input id="btnSearch" type="button" value="Search" class="btn_Search" />
<div class="row">
<div class="col-sm-12">
#(Html.Kendo().Grid<MvcApplicatioin.Models.EmployeeResponse>()
.Name("GridEmployee")
.Columns(columns =>
{
columns.Bound(e => e.Id).Width("170px").Visible(Model.EmployeeColumns.Id);
columns.Bound(e => e.FirstName).Width("190px").Visible(Model.EmployeeColumns.FirstName);
columns.Bound(e => e.LastName).Width("170px").Visible(Model.EmployeeColumns.LastName);
})
.ToolBar(tools =>
{
tools.Template(#<text>
<div class="col-lg-4 col-md-5 col-sm-5 col-xs-7 pull-right" style="padding-right: 0;">
<div class="form-group" style="margin-bottom: 0;">
#Html.Label("Grid View:", new { #class = "col-sm-3 col-xs-4 control-label view" })
<div class="col-sm-7 col-xs-6" style="padding-left: 0;">
#Html.DropDownList("lstEmployeeViewNames", new SelectList(Model.EmployeeViewNames, "Value", "Text", Model.EmployeeSelectedViewId), "- Select View Name -", new { #class = "form-control", #style = "height: auto;" })
</div>
</div>
</div>
</text>);
})
.Pageable(x => x.PageSizes(new int[] { 10, 20, 50, 100 }).ButtonCount(4))
.AutoBind(false)
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.ServerOperation(false)
.Read(read => read.Action("SearchEmployee", "Employee")))
)
</div>
</div><!--//row-->
<script type="text/javascript">
$('#btnSearch').click(function (e) {
e.preventDefault(); //This prevent the submit button onclick from submitting by itself
$('#GridEmployee').data('kendoGrid').dataSource.read();
});
//Change event for Dropdown placed inside the Grid's Toolbar - To Change the view
$("#lstEmployeeViewNames").change(function (e) {
var selectedViewId = $('select#lstEmployeeViewNames option:selected').val();
if (selectedViewId == null || selectedViewId == '') {
alert("Please select the view name from the dropdown first !!");
return;
}
$.post("/Employee/SetEmployeeColumnsCurrentPreferences", { viewId: selectedViewId }, function (data) {
window.top.location.reload();
});
});
</script>
This is how I would do a search in client. I know it doesn't tell how to show and hide columns, but at least it could put you on the right track.
The trick is to manipulate $("#GridEmployee") instead of posting.
function search() {
var searchCriteria = $("#searchField").val();
var gridData = $("#GridEmployee").data("kendoGrid");
if searchCriteria != "") {
gridData.dataSource.filter({ field: "FirstName", operator: "contains", value: searchCriteria });
} else {
gridData.dataSource.filter({});
}
}

Saving multiple records on submit click into differnt entities in MVC4. Not getting values from view in Controller

I am trying to save the class attendance for multiple students on click of submit button. I am able to create the blank records in the concern tables and then populate the data in view.
I have the following view model:
public class TeacherAttendanceModel
{
#region Required Properties
public long ScholarAttendanceId { get; set; }
public string Student { get; set; }
public bool Absent { get; set; }
public string AbsentComment { get; set; }
public bool Uniform { get; set; }
public bool Homework { get; set; }
public string HomeworkComment { get; set; }
public String UniformCommentSelected { get; set; }
public IEnumerable<String> UniformComment { get; set; }
#endregion
}
My Controller is as below.
public class TeacherAttendanceController : Controller
{
//
// GET: /TeacherAttendance/
public ActionResult Index()
{
long classId = Success.Business.Roles.Teacher.GetHomeRoomClassID(Convert.ToInt64(Session[GlobalVar.LOGGED_IN_ID]));
var classAttendanceStatus = Success.Business.Entities.ClassAttendance.GetClassAttendanceStatus(classId);
ViewBag.status = classAttendanceStatus;
var attendanceData = TeacherAttendance.CreateClassAttendance(classId);
return View(attendanceData);
}
[HttpPost]
public ActionResult Index(IEnumerable<TeacherAttendanceModel> teacherAttendanceModel)
{
try
{
if (ModelState.IsValid)
{
TeacherAttendance.SaveAttendance(teacherAttendanceModel);
}
}
catch (Exception e)
{
}
return View(teacherAttendanceModel);
}
}
Get Index is working fine. But I am not getting the TeacheAttendanceModel object in Post index. I get null object. I would be thank full to get any help in this regards. How to update the multiple records of attendance on submit click?
I am using the following View:
#foreach (var item in Model) {
<tr >
<td style="border-style:solid; border-color:darkslategray; border-width:thin;">
#Html.DisplayFor(modelItem => item.Student)
</td>
<td style="border-style:solid; border-color:darkslategray; border-width:thin;">
#Html.CheckBoxFor(modelItem => item.Absent, ViewBag.status == 2 ? new {disabled = "disabled"} : null)
#Html.TextBoxFor(modelItem => item.AbsentComment, ViewBag.status == 2 ? new {disabled = "disabled"} : null)
</td>
<td style="border-style:solid; border-color:darkslategray; border-width:thin;">
#Html.CheckBoxFor(modelItem => item.Uniform, ViewBag.status == 2 ? new {disabled = "disabled"} : null)
#Html.DropDownListFor(modelItem => item.UniformCommentSelected, new SelectList(item.UniformComment),item.UniformCommentSelected ?? "---Select---", ViewBag.status == 2? new {disabled = "disabled"} : null)
</td>
<td style="border-style:solid; border-color:darkslategray; border-width:thin;">
#Html.CheckBoxFor(modelItem => item.Homework, ViewBag.status == 2 ? new {disabled = "disabled"} : null)
#Html.TextBoxFor(modelItem => item.HomeworkComment, ViewBag.status == 2? new {disabled = "disabled"} : null)
</td>
</tr>
}
Model:
public class Test
{
public List<string> UniformComment { get; set; }
}
Controller:
public ActionResult Index()
{
var model = new Test
{
UniformComment = new List<string>{ "one", "two", "three" }
};
return View(model);
}
[HttpPost]
public ActionResult Index(Test model)
{
return View(model);
}
View:
#using (Html.BeginForm())
{
for (var i = 0; i < Model.UniformComment.Count; i++)
{
#Html.TextBoxFor(x => Model.UniformComment[i])
}
<input type="submit" value="Save" />
}
Rendered html example:
<input id="UniformComment_0_" name="UniformComment[0]" type="text" value="one" />
<input id="UniformComment_1_" name="UniformComment[1]" type="text" value="two" />
<input id="UniformComment_2_" name="UniformComment[2]" type="text" value="three" />
The idea is iterate with for loop or create EditorTemplate and then you receive indexed items.
Added (Feel the difference):
View:
#using (Html.BeginForm())
{
foreach (var comment in Model.UniformComment)
{
#Html.TextBoxFor(x => comment)
}
<input type="submit" value="Save" />
}
Rendered html:
<input id="comment" name="comment" type="text" value="one" />
<input id="comment" name="comment" type="text" value="two" />
<input id="comment" name="comment" type="text" value="three" />
Use a IList instead of IEnumerable in the view and replace the foreach loop with a for loop.
Step 1:
Use
#model IList<TeacherAttendanceModel>
instead of
#model IEnumerable<TeacherAttendanceModel>
Step 2:
Use
#for (var i = 0; i < Model.Count; i++)
instead of
#foreach (var item in Model)
Refer How to pass IEnumerable list to controller in MVC including checkbox state? for more details.