user153923
user153923

Reputation:

How to call javascript after ASP.NET MVC controller method?

I have been tasked with resolving a few bugs on a Razor page.

I know it is ASP.NET MVC, it uses the .NET Framework 4.5.2, and I suspect the version of MVC this project is using is 5.2 because I found this in the Web.config file:

<dependentAssembly>
    <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>

The @Html.BeginForm() is used without parameters and has an <input type="submit" />:

@using (Html.BeginForm())
{
//
   <input type="submit" value="Submit" class="submit"" />

It will call either method RetailActivity() or RetailActivity(MyModel model) in the AdminController.cs.

The documentation for Html.BeginForm shows several overloads that I have no experience with.

The HTML has a basic "wait" image that shows while the Database Server is retrieving data:

<div id="loadingDiv" style="position:fixed; top: 50%; left: 50%">
    <img src="~/Images/wait.gif" />
    <br />Loading. Please Wait.
</div>

In Javascript, the "wait" DIV shows when the DropDown lists are populated with the AJAX calls.

var $loading = $('#loadingDiv').hide();

$(document).ready(function () {
    $(document).ajaxStart(function () {
        $loading.show();
    })
    $(document).ajaxStop(function () {
        $loading.hide();
    });
});

function getDealers(e) {
    let dealership = document.getElementById("DealerID");
    let value = $(dealership).val();
    $.get("@Url.Action("GetDealers", "Admin")?region=" + value, function (res) {
        var markup = "";
        for (var i = 0; (res != null) && (i < res.length); i++) {
            markup += '<option value=' + res[i].Value + '>' + res[i].Text + '</option>';
        }
        $('#DealerID').prop('disabled', false);
        $("#DealerID").html(markup).show();
    });
}

Those are working, but I want a way to show and hide the div when the main FORM SUBMIT is triggered.

I've seen that I can put Javascript in the Html.ActionLink:

how to call javascript function in html.actionlink in asp.net mvc?

...but I don't see a way to do that in the Html.BeginForm part of Razor.

So, I edited my Html.BeginForm so that I could manually handle the call in Javascript:

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "myForm" }))
{
//
   <input type="button" value="Submit" class="submit" onclick="formSearch();" />

So far, I've tried formSearch() two (2) ways:

function formSearch_old() {
    var value = $('#DealerID').val();
    var text = $('#DealerID :selected').text();
    console.log('Inside formSearch() routine: value=' + value + ', text=' + text);
    $loading.show();
    console.log('showing spinner');
    $.get("@Url.Action("RetailActivity", "Admin")?model=" + Model);
    $loading.hide();
    console.log('hiding spinner');
    $('#DealerID').val(value);
    console.log('DealerID set to ' + value);
}

function formSearch() {
    var value = $('#DealerID').val();
    var text = $('#DealerID :selected').text();
    history.go(-1);
    console.log('Inside formSearch() routine: value=' + value + ', text=' + text);
    $loading.show();
    console.log('showing spinner');
    $("#myForm").submit();
    $loading.hide();
    console.log('hiding spinner');
    $('#DealerID').val(value);
    console.log('DealerID set to ' + value);
}

In the old version, this line executes immediately:

$.get("@Url.Action("RetailActivity", "Admin")?model=" + Model;

That doesn't work because Model is undefined. I tried using @Model instead, but that just provided the fully qualified string name of the class.

The current version uses this line:

$("#myForm").submit();

It executes fine. In the Console Window, I have this data:

Inside formSearch() routine: value=159200, text=Dri-Port Marine
RetailActivity:222 showing spinner
RetailActivity:226 hiding spinner
RetailActivity:228 DealerID set to 159200

But, it finishes running immediately while my form is still waiting for the Database Server to return the data.

So that is what I've tried.

Should I fix one of the Javascript formSearch() methods or use an overload for the Razor @Html.BeginForm() call?

I hope this isn't too complicated. It took hours to write out.

Upvotes: 1

Views: 361

Answers (1)

Shiin Zu
Shiin Zu

Reputation: 166

This is how I set it up in my project, this code is not really mine, but I can't remember the source. Use the following JavaScript function and modify it for your own purpose:

function disableSecondCLick (ctl, msg, form = null, isThisAForm = true) {
  const isFormValid = $(form).valid()
  if (isFormValid) {
    $(ctl).prop('disabled', true).text(msg);
    $('.submit-progress').removeClass('invisible').addClass('visible');
    $('body').addClass('progress-body-bg');
    if (isThisAForm) {
      $(form).submit();
    }
    //I encase my form controls inside a <fieldset> to disable them during submit. 
    //This prevents the user from messing with them during the process.
    $('fieldset').prop('disabled', true); 
  }
  return true;
}

This is a function I use whenever I need to disable a button and display a progress div. Then in your submit button add an onclick event handler and call it as shown:

 <button class="btn btn-primary" type="submit" form="form1" onclick="disableSecondCLick(this,'Submitting...','#form1',true);">Submit</button>

In your CSS file add the following class to darken the background when you're showing the progress div:

.progress-body-bg {
    background-color: lightgray;
    opacity: .5;
}

Upvotes: 1

Related Questions