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

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

  •  03-10-2022
  •  | 
  •  

Pergunta

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.

Foi útil?

Solução

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top