Reputation: 5
I'm currently programming in MVC 2.1 and I've run into a problem. My main view is displaying a list of members using the model IEnumerable. I want to have a form on that page which will populate with the selected member's information when clicked. For this to happen I would need to pull data from a specific instance of Members.
I have this functional using different views, but I wanted to know if it was possible using only one view.
Upvotes: 0
Views: 93
Reputation: 21656
I want to have a form on that page which will populate with the selected member's information when clicked. For this to happen I would need to pull data from a specific instance of Members.
According to your description, the Members and the Member's Information table should be contains the relationship (One-to-One or One-to-Many). To display the member's information when click the selected member, I think it is better to use JQuery ajax to achieve it.
Try to add a "Details" button in the row, when click it, using JQuery ajax to get the selected Member's information (based on the MemberID property). You could refer to the following samples:
Create Member and MemberInformation class and configure relationship (assume it contains the One-to-one relationship):
public class Member
{
public int MemberID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public MemberInformation MemberInformation { get; set; }
}
public class MemberInformation {
public int ID { get; set; }
public string Address { get; set; }
public DateTime BirthDate { get; set; }
public string City { get; set; }
[ForeignKey("Member")]
public int MemberID { get; set; }
public Member Member { get; set; }
}
Create controller action methods:
// GET: Members
public async Task<IActionResult> Index()
{
return View(await _context.Members.ToListAsync());
}
//get the MemberInformation based on the MemberId
[HttpPost]
public JsonResult GetMemberInformation(int memberid)
{
return Json(_context.MemberInformation.Where(c => c.MemberID == Convert.ToInt32(memberid)).FirstOrDefault());
}
Create the Main View:
In the View Page, after display the Member, add a form to display the selected member's information. Then, using jquery to find the selected Memberid, and based on the value to use Ajax method to get the member's information.
@model IEnumerable<netcore2_1.Models.Member>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p><a asp-action="Create">Create New</a></p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Email)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Email)
</td>
<td>
<a asp-action="Details" class="link_detail" data-memberid="@item.MemberID" asp-route-id="@item.MemberID">Details</a>
</td>
</tr>
}
</tbody>
</table>
<div>
<h2>Member Information</h2>
<div id="memberinfo">
<form asp-action="DisplayMemberInformation">
<input type="hidden" id="memberinfoid" name="ID" />
<div class="form-group">
<label for="Address" class="control-label">Address</label>
<input id="txtaddress" name="Address" class="form-control" />
</div>
<div class="form-group">
<label for="BirthDate" class="control-label">BirthDate</label>
<input id="txtBirthdate" name="BirthDate" class="form-control" />
</div>
<div class="form-group">
<label for="City" class="control-label">City</label>
<input id="txtCity" name="City" class="form-control" />
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
@section Scripts{
<script src="~/lib/jquery/dist/jquery.js"></script>
<script type="text/javascript">
$(function () {
$(".link_detail").each(function (index, item) {
$(item).click(function () {
event.preventDefault(); //prevent the default event.
//get the selected memberid.
var memberid = parseInt($(this).attr("data-memberid"));
$.ajax({
type: "POST",
url: "/Members/GetMemberInformation",
data: { memberid: memberid },
success: function (data) {
//populate the Form.
$("#memberinfoid").val(data.ID);
$("#txtaddress").val(data.Address);
$("#txtBirthdate").val(data.BirthDate);
$("#txtCity").val(data.City);
},
failure: function (response) {
console.log(response.responseText);
},
error: function (response) {
console.log(response.responseText);
}
});
});
});
});
</script>
}
The result like this:
Besides, you could also use a partial view to display the Member's information, and use JQuery Ajax dynamic adds the partial view to the Main View.
Create a Partial View:
@model netcore2_1.Models.MemberInformation
<h4>MemberInformation</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="DisplayMemberInformation">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="ID" />
<div class="form-group">
<label asp-for="Address" class="control-label"></label>
<input asp-for="Address" class="form-control" />
<span asp-validation-for="Address" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BirthDate" class="control-label"></label>
<input asp-for="BirthDate" class="form-control" />
<span asp-validation-for="BirthDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="City" class="control-label"></label>
<input asp-for="City" class="form-control" />
<span asp-validation-for="City" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MemberID" class="control-label"></label>
<input asp-for="MemberID" readonly class="form-control" />
<span asp-validation-for="MemberID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
</div>
</div>
Add a DisplayMemberInformation method: Using JQuery Ajax to call this method and display the member information.
[HttpPost]
public IActionResult DisplayMemberInformation(int memberid)
{
var memberinfo = _context.MemberInformation.Where(c => c.MemberID == memberid).Select(c => c).FirstOrDefault();
return PartialView("DisplayMemberInformation", memberinfo);
}
Code in the Main View:
@model IEnumerable<netcore2_1.Models.Member>
@{ ViewData["Title"] = "Index"; }
<h2>Index</h2>
<p> <a asp-action="Create">Create New</a></p>
<table class="table">
<thead>
<tr>
<th> @Html.DisplayNameFor(model => model.Name) </th>
<th> @Html.DisplayNameFor(model => model.Email) </th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model) {
<tr>
<td> @Html.DisplayFor(modelItem => item.Name) </td>
<td> @Html.DisplayFor(modelItem => item.Email) </td>
<td>
<a asp-action="Details" class="link_detail" data-memberid="@item.MemberID" asp-route-id="@item.MemberID">Details</a>
</td>
</tr>
}
</tbody>
</table>
<div id="partial_info">
</div>
@section Scripts{
<script src="~/lib/jquery/dist/jquery.js"></script>
<script type="text/javascript">
$(function () {
$(".link_detail").each(function (index, item) {
$(item).click(function () {
event.preventDefault();
var memberid = parseInt($(this).attr("data-memberid"));
$.ajax({
type: "POST",
url: "/Members/DisplayMemberInformation",
data: { memberid: memberid },
success: function (data) {
//populate the Form.
$("#partial_info").html("");
$("#partial_info").append(data);
},
error: function (response) {
console.log(response.responseText);
}
});
});
});
});
</script>
}
Finally, if you want to directly show multiple objects in the Main view, you could try to create a ViewModel which contains the multiple objects, then display the ViewModel in the Main View. Or, you can use ViewBag or ViewData. More detail information, check Passing data to views
Besides, if these objects contain relationships, try to refer Read related data - ASP.NET MVC with EF Core
Upvotes: 0
Reputation: 745
Easiest design would be to create a view model that contains the collection of the members and a model for a member. Upon clicking the member name on the html page, your form will submit an identifier of the member (eg. name), and the receiving action will return the model containing the collection of members and populate the member model. Take a look at the model below:
public class MyViewModel
{
public IEnumerable<string> MembersList { get; set; }
public Member Member { get; set; }
}
public class Member
{
public string MemberName { get; set; }
public string MemberId { get; set; }
}
And in your controller, you should have an action similar to this:
[Post]
public IActionResult Index(string memberName)
{
//Maybe add some validation.
MyViewModel model = new()
{
MembersList = MethodThatPopulatesTheMembers(),
Member = MethodThatGetsTheMemberByMemberName(memberName)
};
return View(model);
}
Btw you will encounter a null reference error during the initial display of the page and if the Member is null (i.e. your method couldn't find the member with that name because you made a mistake on the programming or the member got deleted) . To remedy this, you may create a new instance for your Member object or hide the html fields that are bound to the Member model if it is null.
Once you are more comfortable with synchronous page requests, consider practicing on asynchronous page requests. You might want to take a look at fetch.
Upvotes: 0