2

I have a table that lists the courses in the system with a Select button for each Course (in a row). When I click Select, the enrolled users of that course are displayed. The Course entity has navigation property public List<CourseRegistration> CourseRegistrations { get; set; }

I have this ViewModel for this purpose:

public class CourseIndexViewModel
{     
    public int SelectedCourseId { get; set; }

    public List<Course> Courses { get; set; }
}

Just under the enrollments list (or registrations) I have a textbox (for keyword) and button to search users for enrollment. I use AJAX to execute an action of controller (UserController) (to which I pass the keyword) which searches users in the db, and passes the result set to a partial view, which returns a table of users with Enroll button in each row.

Everything works fine so far. Now, I need to implement the Enroll button inside the Partial View. However, I will need the id of the course, which is actually available in the main view (i.e., SelectedCourseId). Is there a way to access that value from the partial view? Do I have to (or should I) use hidden input for this purpose?

The biggest challenge is updating the enrollment list shown in the main View after enrolling a new user. I want to use Ajax to do that to prevent page refresh.

Is it feasible and recommended to use Ajax to get the enrollments again from the database and replace the existing enrollments table in the main view with the new table generated in the partial view?

UPDATE Here is the main view:

@model EcholuMvc.Models.CourseIndexViewModel

<table class="table">
    <tr>
        <th></th>
        <th>
            CourseTitle
        </th>           
        <th></th>
    </tr>

    @foreach (var item in Model.Courses)
    {
        <tr @(Model.SelectedCourseId == item.CourseId ? "style=background-color:whitesmoke;" : "style=" )>
            <td>
                @Html.ActionLink("Select", "Index", new { courseId = item.CourseId })
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.CourseTitle)
            </td>                
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.CourseId }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.CourseId })
            </td>
        </tr>
        if (Model.SelectedCourseId == item.CourseId)
        {
            <tr>
                <td>
                    <h4>Enrolled users:</h4>
                    <table class="table">
                        <tr>
                            <th>First name</th>
                            <th>Last name</th>                                
                            <th></th>
                        </tr>
                        @if (item.CourseRegistrations.Count > 0)
                        {
                            var registrations = item.CourseRegistrations;
                            foreach (var reg in registrations)
                            {
                                <tr>
                                    <td>
                                        @reg.Member.FirstName
                                    </td>
                                    <td>
                                        @reg.Member.LastName
                                    </td>                                        
                                    <td>
                                        @Html.ActionLink("Delete", "Delete", new { memberid = reg.MemberId, courseid = reg.CourseId })
                                    </td>
                                </tr>
                            }
                        }
                        else
                        {
                            <tr>
                                <td colspan="4">No enrollment!</td>
                            </tr>
                        }

                    </table>
                    <div class="container-fluid">
                        <div class="row">
                            <div class="col-sm-9">
                                <input id="txt_SearchUser" placeholder="Enter a name.." class="form-control " type="text" />
                            </div>
                            <input id="btn_SubmitUserSearch" class="btn btn-default btn-sm col-sm-3" type="button" value="Search" />
                        </div>
                        <div class="row">
                            <div id="div_UserSearchResults" class="col-sm-12">

                            </div>
                        </div>
                    </div>
                    <script>
                        $("#btn_SubmitUserSearch").click(function () {
                            $.ajax({
                                url: 'Account/SearchUsers',
                                contentType: 'application/html; charset=utf-8',
                                data: { keyword: $('#txt_SearchUser').val() },
                                type: 'GET',
                                dataType: 'html'
                            })
                            .success(function (result) {
                                $('#div_UserSearchResults').html(result);
                            })
                            .error(function (xhr, status) {
                                alert(status);
                            })
                        });
                    </script>
                </td>
            </tr>
        }
    }

</table>

And, here is the partial view:

@model IEnumerable<EcholuMvc.Models.ApplicationUser>

<table class="table-striped" >
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.FirstName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.LastName)
        </td>
        <td>
            <select id="drp_Role">
                <option value="Student" selected="selected">Student</option>
                <option value="Instructor">Instructor</option>
            </select>
        </td>
        <td>
            <input id="btn_Enroll" data-userid="@item.Id" type="button" />
        </td>
    </tr>
}

</table>
renakre
  • 8,001
  • 5
  • 46
  • 99

1 Answers1

3

If you simply want the selected courseId in client side (for your ajax submit of new enrollment or any other thing), you may add a hidden field to the main view and read it from that when needed.

@Html.HiddenFor(s=>s.SelectedCourseId)

Now whenever you need it for your ajax posts, just read the value of this and use

var selectedCourseId=$("#s.SelectedCourseId").val();

But If you want the courseId in your search functionality for some reason, you may pass the selected courseId to your ajax call as a parameter. Keep the course id as the html 5 data attribute to your search input field

<input id="txt_SearchUser" placeholder="Enter a name.."
               data-course="@item.CourseId" class="form-control " type="text" />

Now when you make the ajax call, read this value and send it.

$("#btn_SubmitUserSearch").click(function () {
     $.ajax({
             url: 'Account/SearchUsers',
             data: { keyword: $('#txt_SearchUser').val(),
                     courseId:$('#txt_SearchUser').data("course") },
             type: 'GET',
             dataType: 'html'
            })
            .success(function (result) {
                $('#div_UserSearchResults').html(result);
            })
            .error(function (xhr, status) {
               alert(status);
           })
});

Make sure your SearchUsers endpoint accept this new param and pass that to the resulting partial view it will render.

public ActionResult SearchUsers(string keyword,int courseId)
{
  // to do : Do something with the passed values
  // to do : return something
}

Also i assume that, with your if condition you are rendering only one search form in your page because you cannot have duplicate id's. Also consider using Url.Action helper method to generate the proper url to the action method instead of hardcoding the url as explained in this post.

Community
  • 1
  • 1
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Thanks for the answer @Shyju! How about updating the course registration list in the parent view when a new user is enrolled in the partial view? Should I just use ajax & jquery to insert a new row? – renakre Feb 28 '16 at 16:02
  • 1
    You are making an ajax call to add the new enrollment. So you have all the values in your client side. so either build the html markup for the new row and append that to the table (Ex : `$("#YourTableId").append("Hi");` or when you make the ajax call, let the server reply with a partial view which is the markup for the new row. – Shyju Feb 28 '16 at 16:05
  • I guess it should fine if I use `@item.CourseId` instead of `$('#txt_SearchUser').data("course") }` for the ajax call? Thanks! – renakre Feb 28 '16 at 17:14
  • 1
    `@item.CourseId` is server code and get's executed on the server. You cannot execute that again from your js code. That is the reason we keep it in the data attribute of the input field which razor will render properly and the client script can access it. – Shyju Feb 28 '16 at 17:16
  • you recommend me to use `Url.Action` method. I wonder if it is okay not to use it if I will make an ajax call for the button/link. – renakre Feb 28 '16 at 20:01