Cannot update database entry and refresh dynamic WebGrid using jQuery - ASP.Net MVC

StackOverflow https://stackoverflow.com/questions/21405612

  •  03-10-2022
  •  | 
  •  

Question

I am successfully dynamically displaying a WebGrid based on selected item of a DropDownList. If I select another item in the DropDownList, I will see a different WebGrid. Before stating what I am trying to do next, here is how I have achieved the above (with plenty of help from people like you).

Here is my Index view:

@model BarClients.Models.BarClientsViewModel

@{
    ViewBag.Title = "Index";
}

<h2>Enter Client Information</h2>
<br />
<table>
    <tr>
        <th align="left">
            @Html.DisplayNameFor(model => model.BAR_Clients.ClientId)
        </th>
    </tr>
    <tr>
        <th valign="top">
            <div id="MeditechDropDown">
                @Html.DropDownListFor(model => model.BAR_Clients.ClientId, Model.MeditechClientID, "-- Select --", new { style = "width:170px" })
            </div>
        </th>
        <th>
            @{Html.RenderAction("EmailAddressGrid", "Home");}
        </th>
    </tr>
</table>

Here is my EmailAddressGrid view:

@model BarClients.Models.BarClientsViewModel

@{
    WebGrid grid = null;
    if (Model.EmailAddressesOfChosenClient.Count<string>() != 0)
    {
        grid = new WebGrid(Model.EmailAddressesOfChosenClient, ajaxUpdateContainerId: "gridContent");
    }
}

<div id="gridContent">
@{ if (grid != null)
   {
       <table>
           <tr>
               <td>
               @grid.GetHtml(           
                columns: grid.Columns(
                grid.Column("Email Addresses", format: item => item)))
               </td>
               <td valign="top">
                   @Html.DisplayFor(model => model.InvoiceMode)
               </td>
           </tr>
       </table>     
   }
}
</div>

Here is the jQuery I am using to dynamically display a WebGrid based on selection of the DropDownList (clientID):

jQuery(document).ready(function () {
    $("#MeditechDropDown").change(function () {
        var id = $(this).find(":selected").val()
        var clientID = { "clientID": id }
        $.ajax({
            url: "/Home/PopulateEmailAddressUI",
            data: JSON.stringify(clientID), // Send value of the drop down change of option
            type: 'POST',
            datatype: 'html',
            contentType: 'application/json; charset=utf-8',
            success: function (response) {
                $('#gridContent').html(response)
            }
        });
    });
});

Here is the controller action PopulateEmailAddressUI that returns the asynchronous WebGrid:

[HttpPost]
public PartialViewResult PopulateEmailAddressUI(string clientID)
{
    _clientModel = InitialiseBarClientsModel();

    _clientModel.FindEmailAddresses(from client in eFormsDB.BAR_Clients where client.ClientId == clientID select client);

    return PartialView("~/Views/Home/EmailAddressGrid.cshtml", _clientModel);
}

So far so good. My next task is to be able to enter a new email address on an Editor. I would then hit an "Add Email" button which would then add it to a database table record identified by the currently selected item of the DropDownList mentioned above. To accomplish this, I have an extra table inside the "gridContent" div ID where the code for the WebGrid resides:

<table>
    <tr>
        <th align="left">
            @Html.EditorFor(model => model.NewEmailAddress)
        </th>
        <th>
            @Html.DropDownListFor(model => model.BAR_Clients.InvoiceMode, Model.InvoiceOptions, new { style = "width:70px" })
        </th>
        <th>
            <div id="AddEmail">
                <button>Add Email</button>
            </div>
        </th>
    </tr>
    <tr>
        <th align="left">
            @Html.Raw("Enter New Email Address")
        </th>
    </tr>
</table>

I (unsuccessful) attempt at having the email address added and the WebGrid reloaded through jQuery is as follows:

jQuery(document).ready(function () {
    var addEmail = $('#AddEmail');
    addEmail.on('click', function () {
        var id = $("#MeditechDropDown").find(":selected").val()
        var clientID = { "clientID": id }
        $.ajax({
            url: "/Home/AddEmailAddress",
            data: JSON.stringify(clientID), // Send value of the drop down change of option
            type: 'POST',
            datatype: 'html',
            contentType: 'application/json; charset=utf-8',
            success: function (response) {
                $('#gridContent').html(response)
            }
        });
    });
});

My controller action AddEmailAddress looks like:

[HttpPost]
public PartialViewResult AddEmailAddress(string clientID)
{
    // Code to update database omitted

    return PartialView("~/Views/Home/EmailAddressGrid.cshtml", _clientModel);
}

Basically after entering a new email address and clicking on the "Add Email" button, nothing is happening (controller action AddEmailAddress never gets called). What am I doing wrong? Things that could be getting in the way are the fact that AddEmail div ID is inside the gridContent div ID. Many thanks for any pointers.

Était-ce utile?

La solution

For things to work the way I intended to, I needed to have one jQuery function that looked like this:

jQuery(document).ready(function () {
    $("#MeditechDropDown").change(function () {
        var id = $(this).find(":selected").val()
        var clientID = { "clientID": id }
        $.ajax({
            url: "/Home/PopulateEmailAddressUI",
            data: JSON.stringify(clientID), // Send value of the drop down change of option
            type: 'POST',
            datatype: 'html',
            contentType: 'application/json; charset=utf-8',
            success: function (response) {
                $('#gridContent').html(response)
                $('button').click(function () {
                    var email = $("#NewEmailAddress").val()
                    var invoice = $("#InvoiceDropDown").find(":selected").val()
                    var emailInfo =
                    {
                        "clientID": id,
                        "emailAddress": email,
                        "invoiceMode": invoice
                    };
                    $.ajax({
                        url: "/Home/AddEmailAddress",
                        data: JSON.stringify(emailInfo),
                        type: 'POST',
                        contentType: 'application/json; charset=utf-8',
                        success: function (response) {
                            $('#gridContent').html(response)
                        }
                    });
                })
            }
        });
    })
});

And my EmailAddressGrid view looks like:

@model BarClients.Models.BarClientsViewModel

@{
    WebGrid grid = null;
    if (Model.EmailAddressesOfChosenClient.Count<string>() != 0)
    {
        grid = new WebGrid(Model.EmailAddressesOfChosenClient, ajaxUpdateContainerId: "gridContent");
    }
}

<div id="gridContent">
@{ if (grid != null)
   {
       <table>
           <tr>
               <td>
                   @grid.GetHtml(
            tableStyle: "webgrid-table",
            headerStyle: "webgrid-header",
            footerStyle: "webgrid-footer",
            alternatingRowStyle: "webgrid-alternating-row",
            selectedRowStyle: "webgrid-selected-row",
            rowStyle: "webgrid-row-style",
            mode: WebGridPagerModes.All,

            columns: grid.Columns(
            grid.Column("Email Addresses", format: item => item)))
               </td>
               <td valign="top">
                   @Html.DisplayFor(model => model.InvoiceMode)
               </td>
           </tr>
       </table>

      <br />
      <table>
          <tr>
              <th align="left">
                  @Html.TextBoxFor(model => model.NewEmailAddress)
              </th>
              <th>
                  <div id="InvoiceDropDown">
                      @Html.DropDownListFor(model => model.BAR_Clients.InvoiceMode, Model.InvoiceOptions, new { style = "width:70px" })
                  </div>
              </th>
              <th>
                  <button>Add Email</button>
              </th>
          </tr>
          <tr>
              <th align="left">
                  @Html.Raw("Enter New Email Address")
              </th>
          </tr>
      </table>     
   }
}
</div>

And My Model class looks like:

public class BarClientsViewModel
{
    private List<string> _clientID;
    private List<string> _emailAddresses;

    public BAR_Clients BAR_Clients;
    public veForms_BAR_Clients veForms_BAR_Clients;
    public string InvoiceMode;

    [EmailFormatVerification]
    public string NewEmailAddress;

    public Exceptions Exceptions;

    public BarClientsViewModel(IEnumerable<veForms_BAR_Clients> meditechClients)
    {
        _clientID = new List<string>();
        foreach(veForms_BAR_Clients client in meditechClients)
        {
            _clientID.Add(client.Number);
        }

        _emailAddresses = new List<string>();
    }

    public void FindEmailAddresses(IEnumerable<BAR_Clients> barClients)
    {
        string emailAddressLine = "";
        foreach(BAR_Clients client in barClients)   // There will only be one client here
        {
            emailAddressLine = client.EmailAddress;
            InvoiceMode = client.InvoiceMode;
        }          

        string[] temp = emailAddressLine.Split(';');
        _emailAddresses = new List<string>();
        _emailAddresses = temp.ToList();
    }

    public string AddEmail(IEnumerable<BAR_Clients> barClients, string emailAddress)
    {
        string emailAddressLine = "";
        foreach (BAR_Clients client in barClients)   // There will only be one client here
        {
            emailAddressLine = client.EmailAddress;
            emailAddressLine = String.Format("{0};{1}", emailAddressLine, emailAddress);
        }

        return emailAddressLine;
    }

    public IEnumerable<SelectListItem> MeditechClientID
    {
        get { return new SelectList(_clientID); }
    }

    public IEnumerable<String> EmailAddressesOfChosenClient
    {
        get { return _emailAddresses; }
    }

    public IEnumerable<SelectListItem> InvoiceOptions
    {
        get { return new SelectList(new List<string>() { "PRINT", "EMAIL", "BOTH" }); }
    }
}

My two EF generated classes are as follows:

public partial class BAR_Clients
{
    public string ClientId { get; set; }
    public string EmailAddress { get; set; }
    public string InvoiceMode { get; set; }
}

And

public partial class veForms_BAR_Clients
{
    public string SourceID { get; set; }
    public string ClientID { get; set; }
    public string Number { get; set; }
    public string Name { get; set; }
}

My relevant controller action methods are as follows:

public ViewResult Index()
{
    _clientModel = InitialiseBarClientsModel();
    return View(_clientModel);
}

[HttpPost]
public PartialViewResult PopulateEmailAddressUI(string clientID)
{
    _clientModel = InitialiseBarClientsModel();

    _clientModel.FindEmailAddresses(from client in eFormsDB.BAR_Clients where client.ClientId == clientID select client);

    return PartialView("~/Views/Home/EmailAddressGrid.cshtml", _clientModel);
}

public PartialViewResult EmailAddressGrid()
{
    _clientModel = InitialiseBarClientsModel();
    return PartialView("~/Views/Home/EmailAddressGrid.cshtml", _clientModel);
}

[HttpPost]
public PartialViewResult AddEmailAddress(EmailInfo emailInfo)
{
    _clientModel = InitialiseBarClientsModel();

    string updatedEmail = _clientModel.AddEmail(from client in eFormsDB.BAR_Clients where client.ClientId == emailInfo.clientID select client, emailInfo.emailAddress);

    var clientToUpdate = eFormsDB.BAR_Clients.Find(emailInfo.clientID);

    try
    {
        eFormsDB.Entry(clientToUpdate).Member("EmailAddress").CurrentValue = updatedEmail;
        eFormsDB.Entry(clientToUpdate).Member("InvoiceMode").CurrentValue = emailInfo.invoiceMode;

        eFormsDB.SaveChanges();
    }
    catch (Exception)
    {
        throw new Exception("General Exception occurred while saving to database");
    }

    _clientModel.FindEmailAddresses(from client in eFormsDB.BAR_Clients where client.ClientId == emailInfo.clientID select client);

    return PartialView("~/Views/Home/EmailAddressGrid.cshtml", _clientModel);
}

private BarClientsViewModel InitialiseBarClientsModel()
{
    BarClientsViewModel clientModel = new BarClientsViewModel(from meditech in meditechDB.veForms_BAR_Clients select meditech);

    return clientModel;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top