This is kind of a unique issue, and I'm still fairly new to MVC, so I'll do the best I can to explain it. I have a page with a third party grid, where each row is a "Company" object. My model for the view is a CompanyManager object, with the search parameters as fields and the list to populate the grid. Users are able to select a row for editing, which brings up a popup. A button outside the grid also opens the same popup for creating a new record.
The content of the popup is in a partial view, AddEdit, and the model for it is the "Company" object. Along with other fields, there is also another third party grid with "Contacts" as records. From the third party grid of "Contacts", I can serialize the records and pass them along on submit.
My problem lies with submitting on the modal popup, which should close when successful and stay open when the Company model (or any Contacts in the grid) fails validation. What's the best way of going about the submit? Currently, I have a button that calls a JavaScript function. In this function, I've tried jquery $.submit, but since the form posts to Index, that would close the popup regardless. I've also tried $.post to post to an Ajax call, but I have a JSON result being returned in the controller for this, which didn't work as I expected- it just outputs the JSON as HTML.
If you do your ajax call with JQUERY like this:
$.ajax({
type: 'POST',
dataType: 'json',
url: '/url/', //url your posting to
data: $('#form-addedit').serialize(), //serialize the data in your form
success: function (result) {
//hide modal
}
});
You should get the JSON Result in 'result'. Notice the dataType says 'json' if it was 'html' it would expect html to be returned. The result will be put into the variable result in the success function call and you can do what you want with the variable then, and determine if you need to close the modal or not.
Also, make sure in your controller, that you are indeed receiving an ajax call - Request.IsAjaxRequest()
You can do this by having a regular button to submit the form, like you would on any in-page form. Set the id of the button, let's say to 'Submit'.
Then validate the form with jQuery and the .click function. Something along the lines of
$("#Submit").click(function () {
var value = $("#your_field").val();
if (/*check for invalid condition*/) {
$("#Error_message").show();
return false;
return true;
});
This should check the value of each field you need to validate. If the validation fails, show the user and error message and return false. This prevents the click event (form submit) from executing. If the validation checks pass, return true to allow the click event which will submit the form and close the window.
Related
I need to pass a list to a view as a hidden input and then when I submit the form, before sending back the data, add some items to the list using jquery like:
$('form').submit(function() {
$("#SelectedIds").val(something like ["1","2"]);
});
I know I can't use input asp-for="SelectedIds" type="hidden", as it return the value as "1,2".
Any thoughts?
My web page uses Jquery to overload a screen. In this overlay, the user can type some detail and click the submit button.
What I'd like to do is, when the user clicks on submit, the overlay doesn't disappear (as it would do with a page refresh), but a message appears, such as "all done"
The question I have though, is, what is the correct return type? I've gotten myself into a muddle I'm sure.
I tried to make the return type string, and return the string. Sadly, this redirected me to a page with the string value.
I then thought I would need to return a ContentResult() with return Content(myString). The result was the same as returning a string.
I then tried to return void, and simply in my controller use ViewBag.Status ="All done"; This now takes me an empty page.
How can I make the message show "All done" or "Complete" without losing the state? Am I trying to do the impossible without Ajax or similar?
Yes, you are trying to do the impossible. When a controller action gets hit on a synchronous request (e.g. a form submission) you are always going to get a full-page load. That's exactly what a synchronous request is. In effect, the "refresh" has already happened before your action code even runs; the return type of the action is irrelevant. For partial updates, you need an asynchronous request, which means AJAX.
The typical approach to this would be to load in your overlay and then, submit the form from the overlay via AJAX, return a partial view and target a container with jQuery. You'd typically create some kind of generic wrapper for your overlays that will do this for all form posts within any overlay.
Alternatively, you could look at returning JSON and using a JavaScript templating engine like Handlebars to populate the view.
Either way it's a good idea to look at wrapping all of this up in some "generic" JavaScript code that will do the same thing for form posts in all of your overlays; then you can stop worrying about the client-side code and focus on just returning the right thing from your controller actions.
If you want to do that WITHOUT ajax, you will need to return the whole underlaying page again, including the popup in a visible state.
What you (probably) SHOULD do is to use ajax and return a json result. Something like this jQuery solution:
$(document).on('click', '[type="submit"]', function(){
var $form = $(this).closest('form');
$.ajax({
url: $form.action,
type: 'post',
data: $form.serialize(),
success: function(response){
// write success message to user
}
});
});
I am using MVC3, C#, Razor, EF4.1, SQLServer 2008.
I have a parent form with a dropdown for "Suppliers". I wish to add a "quick add" link/button that enables the user to quickly add a supplier to the DB which is then available in the dropdown for selection. At present this is achieved by
Parent Page -> Add Supplier Page -> Parent Page(Page Refresh)
Of course on return to the parent page, it refreshes and removes all non saved data - which is a problem. It would be better to have a popup window which then saves the suppliers and then just refreshes the dropdown portion of the parent page form. So I believe I am seeking an approach to:
Parent Page -> Popup(Modal) -> DB Save -> Refresh DropDown in Parent Page (Ajax???) -> close Modal popup.
I would appreciate guidance on the above, as I am a little stuck on the best practice and hopefully simple approach to this.
Many thanks.
I normally do something like this:
Create an 'Add' button that will display a popup. (I use jQuery dialogs. They are simple, free, and easily to implement by just calling .dialog on a div). Inside this dialog have the appropriate fields needed to create a new supplier. Have a 'Save' button in this dialog and have it wired up to a AJAX post. (Again this is very simple using jQuery)
If you do use jQuery its as simple as submitting that form to your controller action that will then call you data access layer to save the new supplier entity. When the AJAX call comes back successfully you can reload the contents of the supplier grid with another AJAX post. All the 'Magic' comes from implementing AJAX really which will allow for you to retain the users input and not reload the whole page. The AJAX call that is executed after the user enters in a new Supplier and clicks save would look something like this:
In your JavaScript:
$.ajax({
url: "ControllerName/SaveNewSupplier",
Data: $('#YourAddNewSupplierFormName').serialize(),
Type: "POST"
Success: function(result) {
// this is what will get called after a successful save and return of your action method on your controller. This is where you will put the call to repopulate the supplier list with the updated list.
UpdateSupplierList(); // This function is created below
}
});
In your controller:
Public JsonResult SaveNewSupplier (NewSupplierModel newSupplier)
{
// save your new supplier through your data access layer
// if save is successful then return
Return Json({success = true}, JsonRequestBehavior.AllowGet)
}
Then to repopulate the initial div that contains all the suppliers do something like this:
In JavaScript:
function UpdateSupplierList()
{
$.ajax({
url: "ControllerName/GetAllSuppliers",
Type: "GET"
Success: function(result) {
$('#SuppliersDiv').html(result.suppliers)
}
And in your controller:
// remember that a lot of this is pseudo code and your will have to implement it better for your situation. But basically its just:
Public JsonResult GetAllSuppliers()
{
var suppliers = db.GetSuppliers()
return Jason({suppliers = suppliers}, JsonRequestBehavior.AllowGet);
}
EDIT: If you are updating a SelectList via jQuery then this article is almost identical to what I explained but goes into much more detail on updating the select list. Hope this helps.
http://www.joe-stevens.com/2010/02/23/populate-a-select-dropdown-list-using-jquery-and-ajax/
I have a dropdown of countries, and an address form. Depending on the country selected, I want to hide/show certain fields. I'm quite new to MVC and MVC3, what is the best way to do this?
I have on the page a 'DropDownListFor' that populates correctly. When this changes, I imagine I need to ask the server which fields to show/hide. I could perhaps put some JQuery into a change event that calls a method, and it returns some json saying visible:true for each field, but I don't know if that's ideal or even how to implement it (possibly $.ajax or something).
Any ideas?
Edit: I should add the hard part of this is asking the server what fields to show for each country as there are many countries and the possibilities are all stored in the database. I am accustomed to webforms not MVC so I would ordinarily postback and have serverside logic, but this isn't an option with MVC afaik...
I have deleted my first answer as it was irrelevant.
With MVC3 you can send an AJAX request to any method.
In HomeController.cs:
public List<string> GetFieldsToShow(string id)
{
// if you routing is left to default, the parameter passed in will be called 'id'
// Do what you gotta do...
List<string> listOfFieldsToShowBasedOnCountry = GetList(id);
return listOfFieldsToShowBasedOnCountry;
}
And in the AJAX call, something like...
$.ajax({
type: 'POST',
url: '/Home/GetFieldsToShow/' + valueOfSelectedDropDownItem,
/*etc...*/
success: function(data){
$(data).each(function(){
$('#' + this).show();
}
}
});
I have a dropdown list on my master page that needs to postback after being changed. After the postback, whatever page initiated the postback needs to be re-displayed.
My question is where do I handle this? Obviously I do not want to have to modify every Action in my project... My guess is to maybe postback to some other fixed action and have that action redirect back to the page that is the referrer. Am I correct? Any thoughts?
Thanks.
Jason
In Site.Master, I ended up wrapping the dropdown within its own form that posted back to a dedicated controller/action.
<% Using Html.BeginForm("ChangeRole", "Home")%>
<div id="roleSelector">Change Role: <%=Html.DropDownList("Role", DirectCast(ViewData.Item("Roles"), SelectList), New With {.onchange = "this.form.submit();"})%></div>
<% End Using%>
In the controller I used the following code to change the mode and then redirected back to the referring URL.
<AcceptVerbs(HttpVerbs.Post)> _
Public Function ChangeRole() As ActionResult
Me.CurrentUser.SetRole(DirectCast([Enum].Parse(GetType(Models.ApplicationRoles), Me.Request.Item("Role")), Models.ApplicationRoles))
Return Redirect(Request.UrlReferrer.ToString())
End Function
I am unsure if this is the recommended way but I have been unable to think of another solution.
When you post back from the dropdown list change what are you doing? Can you maybe handle this in a jQuery call thus eliminating the need to re-display the page at all?
Calls to Action Methods can be asynchronous as griegs says, as such, you can post whatever information you need from the radio buttons to an action method without needing to reload the page.
If you need to update a part of the page, you can replace it with the contents of a rendered action method. If you use the jQuery ajax methods, you can post specific information to your methods.
For example, something like this:
$(document).ready(function()
{
$("#myRadioButton").change(function()
{
//Post to your action method, with the value of the radio button, function to call on success
$.post('yourActionMethodUrl', $(this).val(), function()
{
//Update some part of the page
});
});
});
This is based on memory, so you may need to check the syntax.