Main view stacks on the same page after calling partial view - javascript

I have this action that returns different partial view based on the selected value from the drop down list.
Controller:
[HttpPost]
public ActionResult Foo(SomeViewModel VM)
{
var model = VM
if (Request.IsAjaxRequest())
{
if (model.SelectedValue == 1 || model.SelectedValue == 2 || model.SelectedValue == 3)
{
// ...
return PartialView("PartialView1", model);
}
else if (model.SelectedValue == 4)
{
// ...
return PartialView("PartialView2", model);
}
else (model.SelectedValue == 5)
{
// ...
return PartialView("PartialView3", model);
}
}
return View(model);
}
Main View:
<script src="~/Scripts/jquery-3.2.1.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<div>
<h2>Paint Computation</h2>
#using (Ajax.BeginForm("Foo", "Controller",
new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "Result"
}))
{
<div class="col-md-10">
<h5>Type of Paint</h5>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.DropDownListFor(m => m.SelectedValue, new SelectList(Model.PaintType, "Value", "Text"),
"Please Select", htmlAttributes: new { #class = "form-control" })
</div>
<br />
// Some HTML helpers
<input type="submit" value="Compute" class="btn btn-default" id="Submit" />
</div>
}
</div>
//This is how I render my partial view using jQuery in my main View:
<div id="Result">
<hr />
</div>
<script type="text/javascript">
$(document).ready(function () {
$('#Submit').click(function () {
$('#Result').load('/Controller/Foo');
});
});
</script>
Whenever I clicked the button, the partial view appears, but when I clicked it again for the 3rd or 4th time, the main view content stacks on the same main view. I tried to use the inspect element and that's how I determined that it stacks the same main view elements.
Is my way of calling the partial view is right? As much as possible I want to use ajax for calling the partial view every time the button is clicked. Please guide me to correct it. Thanks.
Here's the of the problem.

<script type="text/javascript">
$(document).ready(function () {
$('#Submit').click(function () {
$.ajax({
type: 'POST',
url: '/Controller/Foo',
cache: false,
contentType: "application/html; charset=utf-8",
dataType: 'html',
success: function (result) {
$('#Result').html(result);
}
});
});
});
</script>
Now it works. I changed my code and use the code above. I use .html() rather than .append() or .replaceWith(). Now every time i click the button, it changes the <div id = "Result> content.

Related

How to send files using modal window and MVC

I have a working modal window that saves an entity to the database, my question is how to send files from the modal?
Here as my current JavaScript function:
$('#btn-save').on('click', function () {
$.ajax({
url: '#Url.Action("CreateModal", "Suggestions")',
type: 'POST',
data: $('#modal-form').serialize(),
success: function (data) {
if (data.success == true) {
$('#suggestion-modal').modal('hide');
location.reload(true);
} else {
$('.modal-content').html(data);
$('#suggestion-modal').modal('show');
}
}
});
});
This part does not send data, but works fine when not using modal and using standard MVC Create template:
<form id="modal-form" method="post" enctype="multipart/form-data">
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.UserId)
<div>
#Html.LabelFor(model => model.Title)
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title, "")
</div>
<div>
#Html.LabelFor(model => model.Images, "Images")
<input type="file" name="upload" multiple />
</div>
<div>
<input id="btn-save" type="button" value="" />
</div>
</form>
I've left the rest of the partial view out as that all works correctly.
EDIT: Just added where my button was in the form. It was there, I just removed much of the code not relevant to the question - should have left the button in. Also added extra model properties - These must be sent with the file, including validation token.
EDIT: Many thanks to Jasen. I've included the JavaScript below for anyone else struggling with this.
$('#btn-save').on('click', function () {
var formData = new FormData($('form').get(0));
$.ajax({
url: '#Url.Action("CreateModal", "Suggestions")',
type: 'POST',
processData: false,
contentType: false,
data: formData,
success: function (data) {
if (data.success == true) {
$('#suggestion-modal').modal('hide');
location.reload(true);
} else {
$('.modal-content').html(data);
$('#suggestion-modal').modal('show');
}
}
});
});

the required anti-forgery form field __requestverificationtoken is not present Error while ajax call

anti-forgery form field “__RequestVerificationToken” is not present
when using jQuery Ajax and the Html.AntiForgeryToken()
How to make ajax request with anti-forgery token in mvc
AJAX Posting ValidateAntiForgeryToken without Form to MVC Action Method
All the answers above did not help me. I get this error in my request with Jquery Ajax call:
"The required anti-forgery form field "__RequestVerificationToken" is
not present"
If I comment [ValidateAntiForgeryToken] attribute at POST action method it is working fine. I want to know why I am getting this error.
#using (Html.BeginForm("Save", "AddPost", FormMethod.Post, new { id = "CreateForm" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>GropPost_Table</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Body, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Body, new { id = "Bf" })
#Html.ValidationMessageFor(model => model.Body)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input id="btnAdd" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Save([Bind(Include = "Body")] GropPost_Table groppost_table)
{
if (ModelState.IsValid)
{
groppost_table.GroupID = 1;
groppost_table.ID = 1;
groppost_table.PostDate = System.DateTime.Now;
db.GropPost_Table.Add(groppost_table);
db.SaveChanges();
return Json(groppost_table);
}
else
{
return Json("we Couldent add your post");
}
}
<script type="text/javascript">
$("#btnAdd").click(function () {
var GropPost_Table = {
"Body": $("#Bf").val()
};
var token = $('#CreateForm input[name=__RequestVerificationToken]').val()
var headers = {};
headers['__RequestVerificationToken'] = token;
$.ajax( {
type: "POST",
url: "#Url.Action("Save","AddPost")",
data: JSON.stringify(GropPost_Table),
contentType: "application/json;charset=utf-8",
processData: true,
headers:headers,
success: function (dataR) {
$("#Bf").val('');
},
error: function (dataR) {
$("#Bf").val('');
alert(dataR.toString());
}
});
});
</script>
I've alway included the Request Verification Token in the data of the POST and not the headers. I would approach it like this:
First add type="submit" to your input button so it will submit the form when clicked. Then in your javascript:
// Listen for the submit event on the form
$('#CreateForm').on('submit', function(event) {
var $form = $(this);
$.ajax({
// Html.BeginForm puts the url in the
// "action" attribute
url: $form.attr('action'),
// Serializing the form will pick up the verification
// token as well as other input data
data: $form.serialize(),
success: function(dataR) {
$('#Bf').val('');
},
error: function(dataR) {
$('#Bf').val('');
alert(dataR.toString());
}
});
// Preventing the default action will keep the form
// from doing a full POST.
event.preventDefault();
});

JQuery ui autocomplete in a MVC partial view only works once

I've been trying to get autocomplete to work for my partial view using JQuery ui. The partial view is updated using AJAX.
The problem is that the autocomplete only works up until the point where the partial view is updated.
This is my partial view
<div id="tagList">
#using (Ajax.BeginForm("AddToTagList", new { urlLocation = Model.UrlLocation }, new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "tagList" }))
{
if (Model.TagList != null)
{
<div class="form-group">
#Html.LabelFor(model => model.Tag.Text, "Tags", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-xs-10">
<div class="input-group" style="max-width: 300px;">
#Html.EditorFor(model => model.Tag.Text, new { htmlAttributes = new { #class = "form-control", #id = "search_term" } })
#Html.ValidationMessageFor(model => model.Tag.Text, "", new { #class = "text-danger" })
<div class="input-group-btn">
<button type="submit" value="Add Tag" class="btn btn-default">+</button>
</div>
</div>
</div>
</div>
}
}
</div>
This is my JavaScript
$(document).ready(function () {
$("#search_term").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Tag/SearchAutoComplete",
type: "POST",
dataType: "json",
data: { term: request.term },
success: function (data) {
response($.map(data, function (item) {
return { label: item.Text, value: item.Text };
}));
}
});
},
});
});
and this is my autocomplete search action
public JsonResult SearchAutoComplete(string term)
{
using (IDocumentSession session = RavenDbConfig.RavenDBDocumentStore.OpenSession())
{
var results = session.Query<Tag>().Where(x => x.Text.StartsWith(term)).ToList();
return Json(results,JsonRequestBehavior.AllowGet);
}
}
So, my question is, how can i make this work even after the partial view has been updated once?
Your problem is when you reload your PartialView you basicaly delete some part of DOM in your html document and create new one. And all your bindings that you add in $(document).ready() event will be lost.
One of the posible solutions for this problem is to place your autocomplete init code in addition to .ready() event in jquery .ajaxSuccess() global event becouse you reload your PartialViews via Ajax. Like this:
$(document).ajaxSuccess(function() {
$("#search_term").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Tag/SearchAutoComplete",
type: "POST",
dataType: "json",
data: { term: request.term },
success: function (data) {
response($.map(data, function (item) {
return { label: item.Text, value: item.Text };
}));
}
});
},
});
});
That way you will init your autocomplete every time you reload PartialView.

Form+Ajax doesn't work properly

Form+Ajax -> Results on exact DIV
3 hours, 53 minutes ago|LINK
Hi,
I need to visualize my partialView (results after a form submission) in a DIV.
I have the following files:
View Man_por.cshtml
...
<div class="col-md4" id="divTabPortfolios">
enter code here#{Html.RenderAction("Load_portfoliosPartial","Management_portfolios");}
<div>
<div class="col-md4" id="divTabPortfolio">
<div>
...
View Load_portfolios_partial
<script src="myscript.js" type="text/javascript"></script>
....
...
#using ( # Html.BeginForm() )
{
....
...
<button type="submit" class=".." value="Open"/>
}
Script MyScript.js
$(function () {
$('form').submit(function () {
if ($(this).valid()) {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
$('#divTabPortfolio').html(result);
}
});
}
return false;
});
});
When it shows the result it open entire page and not a partial view (_layout.cshtml+Page) etc.. and it doesn't update the specified DIV.
How could i solve it?
Use #using (Ajax.beginForm()) instead of #using (Html.beginForm().
MVC supports Ajax forms out-of-the-box.
You then provide the action, controller and selector (UpdateTargetId is set to the id of the panel to update) like this:
<div id="divTabPortfolio">
#using (Ajax.BeginForm("SomeAction", "YourController", new { id = optionalParameters }, new AjaxOptions() { HttpMethod = "Post", UpdateTargetId = "divTabPortfolio" }))
{
}
</div>
No need for your own jQuery/Ajax for this sort of basic Ajax post-backs in MVC/Razor.
So long as your action method returns a PartialView you don't need to do anything else.
As suggested, if you could post more of the page it would help provide specifics

.hide() not working after dialog postaback

I'm having a problem with a jQuery dialog that is probably right in front of me but I can't figure out...
The dialog works fine. It shows the fields and sends the information and, if it's the case, brings back the validation message. My problem is that when I initialize it, I tell it to hide a div inside of if, and it does. On open the div is not there, but if I try to send the information and it brings back the validation message, it shows the div.
Here is the js that calls the dialog:
$(function () {
$('.openDialog').click(function () {
$.ajax({
url: this.href,
type: 'GET',
cache: false,
data: { idUsuario: $('#idUsuario').val() },
success: function (result) {
$('#result').html(result).dialog('open');
$('#formButtom').hide();
}
});
return false;
});
$('#result').dialog({
autoOpen: false,
modal: true,
show: { effect: "drop", direction: "up" },
dialogClass: "dialog",
width: 400,
resizable: false,
position: "center",
buttons: {
"Confirmar": function () {
$("form").submit();
},
"Cancelar":function () { $('#result').dialog('close'); }
}
});
});
function dialogSucces(result) {
if (result.cadastro) {
$('#result').dialog('close');
window.location.href = '/usuario/index';
} else {
$('#result').html(result);
}
}
and here is the html:
<form id="createUsuarioForm">
Nome
<div class="editor-field">
#Html.EditorFor(model => model.Nome)<br />
#Html.ValidationMessageFor(model => model.Nome, String.Empty, new { #class = "text-error"})
</div>
<br />
E-mail / Login
<div class="editor-field">
#Html.EditorFor(model => model.Login)<br />
#Html.ValidationMessageFor(model => model.Login, String.Empty, new { #class = "text-error"})
</div>
<br />
<div id="formButtom" class="row demo-row">
<div class="span2">
<input type="submit" value="Confirmar" class="btn btn-primary" />
</div>
<div class="span2">
#Html.ActionLink("Cancelar", "Index", "Usuario", new { #class = "btn btn-primary" })
</div>
</div>
</form>
I've seen this post: jQuery Show/Hide not working after postback and tried doing this in the function, but it didn't work:
$(function () {
$('.openDialog').click(function () {
$.ajax({
url: this.href,
type: 'GET',
cache: false,
data: { idUsuario: $('#idUsuario').val() },
success: function (result) {
$('#result').html(result).dialog('open');
$('#formButtom').hide();
}
});
return false;
if (this.isPostback) { $('#formButtom').hide(); };
});
Does anyone know what I'm doing wrong?
You didn't show how your dialogSuccess function runs, but I suppose it executes in case of form fault also. If that is, you should to add a line into your if else statement there. Like this:
function dialogSucces(result) {
if (result.cadastro) {
$('#result').dialog('close');
window.location.href = '/usuario/index';
} else {
$('#result').html(result);
$('#formButtom').hide(); // once defected form rendered again,
// div hide directive should be launched again too
}
}

Categories

Resources