I am working on ASP.NET MVC project and have an empty form rendered by MVC controller. Right after it's been rendered, I make an AJAX GET request, and receive JSON data to populate the form.
Everything works fine when I populate each individual field (please see code below), but I have a feeling that there is a better/righter way of how to populate the entire form in one shot. Please help.
In my $.get request, I tried:
$("#content").html(data);
It simply empties my form (all fields disappear).
Then I tried:
$("#content").val(data);
Here, all fields stay blank.
Anyways, here is the code that I have (please see below).
Here is my view (.cshtml file):
#model ViewModels.ProductDetailsViewModel
<form asp-controller="ApiProduct" asp-action="Post" id="content">
<div class="form-group">
<label asp-for="Name" class="control-label">Name</label>
<input asp-for="Name" type="text" class="form-control" id="js-name" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label">Description</label>
<textarea asp-for="Description" rows="5" cols="40" class="form-control" id="js-description"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</form>
#section Scripts {
<script>
var id = #Model.Id;
$.get("/apiproduct/get/?id=" + id, function (data) {
$("#js-name").val(data.name);
$("#js-description").val(data.description);
});
</script>
}
Here is my API controller:
[HttpGet("{id}")]
public IActionResult Get(int id)
{
var product = _repository.GetProductById(id);
return Ok(product);
}
Here is my MVC controller:
public IActionResult Details(int id)
{
var vm = new ProductDetailsViewModel()
{
Id = id;
};
return View(vm);
}
Apri478 ...Your API is giving you JSon result of your product and not html.
Above this line write console.log(data)
$("#content").html(data);
and see your response of API.
If you bind this json to form there are plenty of way.. writing custom js binding or using MVVM like angular or knockout.
try to explain more if this is not what you were expecting.
Related
My scenario here is that on my View, I have multiple field to input number and one field to auto generated result by a formula. I want to be able to pass those value back to my Controller, from there I will calculate and return the result back to View while the input value to calculate still remain. The reason why I don't perform this on my Javascript is because there are some condition that require me to interact with value from lots of others field in others data in database. I intend to do this by passing a whole set of Model from View to Controller, and I don't want to reload the page whenever an input field is input. So far, here's my two methods:
Using Javascript Ajax:
var modelObject = #Html.Raw(Json.Serialize(Model));
This allow me to store and passing Base Model at the beginning only. I can't pass new input value. Is there away for the input to automatically store their value in Model to be used in the code similar to the above?
Using Unobtrusive AJAX and Javascript to activate submit action:
function submit(){
$('#formSubmit').submit();
--OR--
$('#btnSubmit').click();
}
<form id="formSubmit" data-ajax="true" asp-action="Action" method="POST">
<input asp-for="Item.inputValue" onchange="submit()"/>
<button id="btnSubmit" type="submit"></button>
</form>
The button when click works fine with Unobtrusive AJAX. But the Javascript to activate the submit event can't. My page still reload.
What is the right way for me to go? And in which of them, how do I need to fix my code to make it run like I want?
Using Javascript Ajax:
var modelObject = #Html.Raw(Json.Serialize(Model));
This allow me to store and passing Base Model at the beginning only. I
can't pass new input value. Is there away for the input to
automatically store their value in Model to be used in the code
similar to the above?
When using JQuery Ajax to pass the data, you should use the serialize() method to serialize the form, then pass the form data to the controller action method. Code as below:
$("#btnAjax").click(function () {
// var data = $("#mainform").serialize(); //you could set a break point to check the value.
$.ajax({
url:"/Test/CreateProduct", // change the url to yours.
method: "Post",
data: $("#mainform").serialize(),
success: function (response) {
//after getting the response, update the content.
$("#div_partial").html("");
$("#div_partial").html(response); //
},
error: function (error) {
alert("error");
}
});
});
Using Unobtrusive AJAX and Javascript to activate submit action:
function submit(){
$('#formSubmit').submit();
--OR--
$('#btnSubmit').click();
}
<form id="formSubmit" data-ajax="true" asp-action="Action" method="POST">
<input asp-for="Item.inputValue" onchange="submit()"/>
<button id="btnSubmit" type="submit"></button>
</form>
The button when click works fine with Unobtrusive AJAX. But the
javascript to activate the submit event can't. My page still reload.
When using the jQuery Unobtrusive AJAX, first, please make sure you have added the jQuery Unobtrusive AJAX reference in current page, then, make sure you have activated unobtrusive Ajax on the target element.
For example, using the following code, after clicking the submit button, it will submit the mainform to the ProductIndex action method, then update the div_partial contents:
<form asp-action="ProductIndex" id="mainform"
data-ajax="true"
data-ajax-method="Post"
data-ajax-update="#div_partial">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div id="div_partial">
<partial name="_PVProduct.cshtml" data="#Model" />
</div>
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-primary" />
</div>
</form>
More detail information about using jQuery Unobtrusive AJAX, refer this link.
The detail sample code as below:
Model:
public class Item
{
public int ItemId { get; set; }
public string ItemDescription { get; set; }
public decimal ItemUnitPrice { get; set; }
public decimal Quantity { get; set; }
}
public class ProductViewModel
{
public string UserName { get; set; }
public List<Item> Items { get; set; }
}
Controller:
public IActionResult ProductIndex()
{
ProductViewModel newitem = new ProductViewModel()
{
Items = _repository.GetItemViewModels().Select(c => new Item() { ItemId = c.ItemId, ItemDescription = c.ItemDescription, Quantity = c.Quantity, ItemUnitPrice = c.ItemUnitPrice }).ToList()
};
return View(newitem);
}
// Unobtrusive AJAX Post method
[HttpPost]
public IActionResult ProductIndex(ProductViewModel product)
{
return PartialView("_PVProduct", product);
}
//JQuery Ajax Post method.
[HttpPost]
public IActionResult CreateProduct(ProductViewModel product)
{
return PartialView("_PVProduct", product);
}
PartialView (_PVProduct.cshtml): Here I use a partial view to display the Model content, it is easier to update the content with Ajax.
#model WebApplication6.Models.ProductViewModel
<div class="form-group">
<label asp-for="UserName" class="control-label"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<table class="table">
<thead>
<tr>
<th>
ItemId
</th>
<th>
ItemDescription
</th>
<th>
ItemUnitPrice
</th>
<th>
Quantity
</th>
<th></th>
</tr>
</thead>
<tbody>
#for (var i = 0; i < Model.Items.Count(); i++)
{
<tr>
<td>
#Model.Items[i].ItemId
<input asp-for="Items[i].ItemId" type="hidden" />
</td>
<td>
#Model.Items[i].ItemDescription
<input asp-for="Items[i].ItemDescription" type="hidden" />
</td>
<td class="text-right">
<input asp-for="Items[i].ItemUnitPrice" type="text" />
</td>
<td class="text-right">
<input asp-for="Items[i].Quantity" type="text" />
</td>
<td class="text-right">
#(Model.Items[i].Quantity * Model.Items[i].ItemUnitPrice)
</td>
<td></td>
</tr>
}
</tbody>
</table>
</div>
View Page ():
#model WebApplication6.Models.ProductViewModel
<div class="row">
<div class="col-md-4">
<form asp-action="ProductIndex" id="mainform"
data-ajax="true"
data-ajax-method="Post"
data-ajax-update="#div_partial">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div id="div_partial">
<partial name="_PVProduct.cshtml" data="#Model" />
</div>
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-primary" />
<input type="button" value="Ajax Submit" class="btn btn-primary" id="btnAjax" />
</div>
</form>
</div>
</div>
At the end the above view page, add the following scripts: Here I use the jQuery Unobtrusive AJAX CDN reference:
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ajax-unobtrusive/3.2.6/jquery.unobtrusive-ajax.min.js"></script>
<script>
$(function () {
$("#btnAjax").click(function () {
//var data = $("#mainform").serialize();
$.ajax({
url:"/Test/CreateProduct", // change the url to yours.
method: "Post",
data: $("#mainform").serialize(),
success: function (response) {
//after getting the response, update the content.
$("#div_partial").html("");
$("#div_partial").html(response);
//attach change event and then trigger the submit form action..
$(".table> tbody >tr").each(function (index, tr) {
$(tr).find("input[name$='Quantity']").change(function () {
//console.log($(this).val());
$("#btnAjax").click();
});
});
},
error: function (error) {
alert("error");
}
});
});
//attach change event and then trigger the submit form action.
$(".table> tbody >tr").each(function (index, tr) {
$(tr).find("input[name$='Quantity']").change(function () {
//console.log($(this).val());
$("#btnAjax").click();
});
});
})
</script>
}
The output as below:
Submit button: using the Unobtrusive AJAX method submit the form.
Ajax Submit button: Using JQuery Ajax to submit the form.
Quantity Input change event: trigger the Ajax button and then submits the form.
I have an ASP.NET MVC project and currently I am using ViewData["ResultMessage"] to show the result of a form (which is done after the user submits & refreshes the page).
I want to do it right after he clicks submit (without refreshing the page). So I have to use Javascript for that, which I am new with. No experience what so ever.
How my form looks like is this:
<form id="contactForm" method="post" action="..">
<div class="field half first">
<label for="Name">Name</label>
<input type="text" name="Name" id="Name" placeholder="Your name" required />
</div>
<div class="field half">
<label for="Email">Email</label>
<input type="email" name="Email" id="Email" placeholder="Your email" required />
</div>
<div class="field">
<label for="Message">Message</label>
<textarea name="Message" id="Message" rows="5" placeholder="Your message" required minlength="20"></textarea>
</div>
<input type="submit" value="Send Message" />
<p>#ViewData["ContactActionResult"]</p>
</form>
You can see the result is displayed with Razor using ViewData. Now I want to do it without refreshing the page and learn JS on the way.
What I have tried so far:
$(function () {
$("button").click(function (e) {
e.preventDefault()
$.ajax({
type: "POST",
url: "/Receiver",
data: car,
datatype: "html",
success: function (data) {
alert("Congratulations, it worked!");
$('#contactForm').html(data);
},
error: function(data) {
alert("Failed.");
}
});
});
});
But I am not sure if I did something wrong or simply not implementing it right. I have the above function inside <script> here </script> in my HTML page. Nothing happens when I click the submit button on the form.
If it is an ajax call, It is best if you return a JSON response . You can use the Request.IsAjaxRequest() to determine whether the request is normal form request or ajax call.
You should also consider using to the PRG pattern. After successfully saving, you should do a redirect to a GET action where you can render a view, instead of returning to the same view with a viewbag message. If you want to pass some message to the new view/action, use TempData instead of ViewData.
[HttpPost]
public ActionResult Receiver(string name, string Email)
{
// Your existing code to save
if(Request.IsAjaxRequest())
{
return Json(new { status = "success", message = "Created successfully" });
}
// Normal form submit. So let's follow PRG pattern
TempData["ResultMessage"] = "Created successfully";
return RedirectToAction("Index");
}
You can also put a try/catch and return a json like this for error usecase
return Json(new { status = "error", message = "some serious error" });
In Index action/view, you can read TempData["ResultMessage"] and display to user.
Now, for the ajax usecase, in your current view, you can add a div to show the message
<form id="contactForm" method="post" asp-action="Receiver">
<div id="msg"></div>
<div class="field half first">
<label for="Name">Name</label>
<input type="text" name="Name" id="Name" placeholder="Your name" required />
</div>
<div class="field half">
<label for="Email">Email</label>
<input type="email" name="Email" id="Email" required />
</div>
<div class="field">
<label for="Message">Message</label>
<textarea name="Message" id="Message" rows="5"
placeholder="Your message" required minlength="20"></textarea>
</div>
<input type="submit" value="Send Message" />
</form>
and now in your ajax call's success callback, check the json response coming back from server and show the message property as needed. If you are putting the script inside the razor view file, make sure you are putting it inside a Scripts section so that it will be evaluated in the proper order (After jQuery is loaded, assuming you load jQuery before calling RenderSection("scripts") inside the layout)
#section Scripts
{
<script>
$(function (){
$("#contactForm").submit(function (e){
e.preventDefault()
$.ajax({
type: "POST",
url: $(this).attr("action"),
data: car,
success: function (data){
if (data.status === "success")
{
$('#msg').html(message);
}
//to do : handle statuss=="error" as needed
},
error: function (data)
{
alert("Failed.");
}
});
});
});
</script>
}
For asp.net core, you can write a IsAjaxRequest method in your base controller and use that. jQuery will add X-Requested-With header with value XMLHttpRequest for your ajax calls.
protected bool IsAjaxRequest()
{
return Request.Headers["X-Requested-With"] == "XMLHttpRequest";
}
I'm still new to how Web API 2.0 works but I'm starting to get the hang of things. The one issue I've been having though is how to post a form along with multiple files that the user uploaded to my controller.
I guess I mainly need help with how to use JavaScript or jquery with ajax to post all of the correct values.
Here is a snippit of my HTML:
<form id="CreateAnnouncementForm" class="form-horizontal">
<input type="hidden" name="announcementTypeID"/>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="col-sm-2 control-label">Headline</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="headline" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">More Info</label>
<div class="col-sm-10">
<textarea class="form-control" name="moreInfo"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Attachments</label>
<div class="col-sm-10">
<input type="file" name="Attachments" multiple/>
</div>
</div>
</div>
</div>
</div>
</form>
Here is the JavaScript/jQuery/Ajax that I normally use to post my form to the controller:
onAnnouncementCreate: function () {
var form = $("#CreateAnnouncementForm");
var validator = $(form).kendoValidator().data("kendoValidator");
if (validator.validate()) {
var options = {
url: getApiUrl() + "/Announcement",
dataType: "json",
type: "POST",
headers: {
"Authorization": "Bearer " + getJwtToken(),
"LocationId": getCurrentLocation()
},
data: $(form).serialize(),
statusCode: {
200: function () {
$("#AnnouncementCreateModal").modal("hide");
announcementViewModel.reloadGrids();
},
400: function (response) {
toastr.options = { "positionClass": "toast-bottom-full-width";
toastr.error(response.responseText);
}
}
};
$.ajax(options);
}
}
Now I believe it would be best if I just created a ViewModel that contained both the ViewModel for all of the values in my form and have it contain an IEnumerable for the attachments that the users can upload within the form.
The trouble I'm having though is correctly adding the attachments to the form so that they map correctly.
My ViewModel will look like this:
public class AnnouncementCreateViewModel
{
public AnnouncementViewModel Announcement { get; set; }
public IEnumerable<HttpPostedFileBase> Attachments { get; set; }
}
Of course I would then need to change the names in my form to reflect the new model.
If anyone can help me on how to post them to my controller that would be much appreciated as that's the only thing I'm still struggling with.
Since this turned out to be more difficult than I thought it would be. I decided to go an alternative route.
Since I'm already using the Kendo UI framework, I am now using the Kendo Upload widget to handle the uploading of my files. I have it asynchronously upload the files to my Web API controller and then I have a separate action to handle the form when it's submitted.
Of course I'm welcome to other answers as well that might be able to solve this issue by posting all of the data in one call but for now, this will do.
I've looked at several existing questions on here already. They're all for submitting post requests, but the mechanics should be the same for get requests, so I modified my code to work for get requests. But it's not working correctly.
What's wrong: I submit a form, but the page continues to reload (right now it's redirecting to a new page with the json data.
What I want to do: Submit a form, prevent it from reloading, and display the json data on the same html page
<div class="row">
<div class="col-md-3">
<form method="GET" action="/search">
<div class="form-group">
<input type="text" class="form-control" id="term" name="term" placeholder="Find">
<br>
<input type="text" class="form-control" id="location" name="location" placeholder="Near">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
<script>
$(function() {
$('form').submit(function(event) {
event.preventDefault();
var $this = $(this);
$.get($this.attr('action'), function(data) {
$('pre').text(data);
});
});
});
</script>
And in my express code, I have this:
app.get('/search', function(req, res) {
var apiUrl = getApiUrl(req.query);
var apiData = getApiData(apiUrl, function(statusCode, data) {
// console.log(data);
// res.render('api-guide', data);
res.send(data);
});
});
I should note, I'm using handlebars for templating. So the form is in its own template, while the jquery script is in the main template. Would this be why it's not working as expected?
Can someone please help me?
You are setting an action parameter in your form that is conflicting with your AJAX request. If you remove
action="/search"
and set the path directly in your AJAX request
$.get('/search', function(data) {
$('pre').text(data);
});
from your form declaration, it should work as you expect.
I am using Ajax.Begin Form to post data on a form without refreshing whole page, I need to validate the textbox, if it has value then the data should be posted else validation message should be shown, but the problem is validation and posting data are both occurring at same time. If I do not add jquery.unobtrusive-ajax.js file then my partial view would is returning as separate white page but validation is working and form is not posting until the textbox has value, BUT if I add jquery.unobtrusive-ajax.js file on page, it is posting data whether textbox has value or not. What is wrong with the code, I am not getting this at all. Please help I have spent two days tried my possible solutions and still no success.
This is my Main View(Parent View) having PartialView
<div id="div_SearchPatient2">
#Html.Partial("SearchPatientPartial");
</div>
#Scripts.Render("~/bundles/jqueryval")
jqueryval is a bundle which has jquery.unobtrusive-ajax.js file.
<div>
#using (Ajax.BeginForm("Search", "Patient", new { },
new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "patientfound"
},
new
{
#name = "SearchPatientForm",
#id = "frmSearchPatient",
}
))
{
#Html.AntiForgeryToken()
<div class="form-title">
Enter MR Number to search patient
</div>
<div class="col-lg-4">
<div class="form-group">
<div class="col-lg-6">
<label class="control-label">MR Number</label>
</div>
<div class="col-lg-6">
<input type="text" class="form-control" name="command" data-mask="999-99-99" placeholder="000-00-00" required data-bv-notempty="true" data-bv-notempty-message="MRNo. is required." />
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-4">
<input class="btn btn-darkorange" type="submit" value="Search" />
</div>
</div>
<div id="patientfound">
#Html.Partial("PatientFoundPartial")
</div>
}
</div>
Where patientfound is a div which will render details if found. I have given this in UpdateTargetId of AjaxBeginForm.
My Controller is returning PartialView
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Search(FormCollection collection, string id)
{
// some code to get data
return PartialView("PatientFoundPartial");
}
In the Ajax option write like this :
OnBegin = "return StartValidation();"
Now define a javascript function called StartValidation with this code :
function StartValidation(){ if($('fromid').validate()){return true;}return false;}