How to call success callback function of knockout model from AjaxForm in mvc - ajax

I'm a newbie in web. Now I'm learning mvc and i have a question. A have a knockout model and a Ajax.BeginForm. I can call "Todo" function as callback without error but it can't work when I try to use "success" function in model like (new AjaxOptions() { HttpMethod = "Post", OnSuccess = "LoginViewModel.success")
#using (Ajax.BeginForm("Todo", "Account", new AjaxOptions() { HttpMethod = "Post", OnSuccess = "Todo" }))
{
<input type="text" name="UserName" data-bind="value: name"/>
<br />
<input type="password" name="Password" data-bind="value: password"/>
<input type="submit"/>
}
<script type="text/javascript">
function LoginViewModel() {
var self = this;
self.name = ko.observable("Hello");
self.password= ko.observable("1234");
self.success = function () {
alert("Hello!");
};
}
ko.applyBindings(new LoginViewModel());
function Todo(data, status, xhr) {
alert("asd");
}
</script>

You should do the following:
var viewModel = new LoginViewModel();
ko.applyBindings(viewModel);
Then you can use:
(new AjaxOptions() { HttpMethod = "Post", OnSuccess = "viewModel.success")
You can see here that you need to create an object of the view model and then call the success method of the object.
I'd also recommend to just use jquery for the ajax calls instead of using the ajax in mvc.

Related

ASP.NET MVC ViewBag values not being displayed in view after Ajax call

I have following view and controller code:
Index.cshtml
#using (Html.BeginForm("Create", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<span style="color:green; font-weight:bold;" id="Message">#ViewBag.Message</span>
<input type="text" id="txtMessage" />
<input type="submit" id="btnSubmit" value="Submit" />
}
<script src="~/Scripts/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$('#btnSubmit').click(function (event) {
$.ajax({
type: "POST",
url: "/Home/Create",
dataType: "json",
contentType: "application/json; charset=utf-8",
async: false,
data: JSON.stringify({
'message': $('#txtMessage').val()
})
});
});
</script>
Controller code:
public class HomeController : Controller
{
public ActionResult Index(string message)
{
return View();
}
[HttpPost]
public ActionResult Create(string message)
{
ViewBag.Message = message;
return View("Index");
}
}
After clicking the button and making ajax call I'm not able to see the message set in the Create method to ViewBag.Message inside the index view.
If you are using Begin form and button type as submit then why write ajax method?
Remove your btnSubmit click from javascript code and use textbox as TextBoxFor,
#Html.TextBoxFor(m => m.message, new { #class = "form-control" })
it should work.
Update Answer for without strongly type
As per code, you are using Begin Form so not required to ajax call.
So first remove javascript code or if you keep that code so no meaning of that.
Now need to update the following line:
<input type="text" id="txtMessage" **name = "txtMessage"** />
And in the controller code post method the following name should be the same.
[HttpPost]
public ActionResult Create(**string txtMessage**)
{
ViewBag.Message = **txtMessage**;
return View("Index");
}

Load/Refresh only part of a page (View) using AJAX in ASP.NET MVC

I am trying to achieve the same result as mentioned by the OP in this post However when I try to render partial view by checking if it was an AJAX request in my Index action, its evaluating to false.
My Index View:
#using (Ajax.BeginForm("Index", "Home",
new AjaxOptions()
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "restaurantList"
}))
{
<input type="search" name="searchTerm" />
<input type="submit" value="Search By Name" />
}
#Html.Partial("_Restaurant",Model)
My Partial View:
<div id="restaurantList" style="border:2px dotted red; padding-left:2em; margin-top:4px;">
#foreach (var item in Model)
{
<div>
<h4>#item.Name</h4>
<div>#item.City, #item.Country</div>
<div>#item.CountOfReviews</div>
<hr />
</div>
}
</div>
My Index Action:
public ActionResult Index(string searchTerm = null)
{
var model = ...//Building model object here
if (Request.IsAjaxRequest())
{
return PartialView("_Restaurant", model);
}
return View(model);
I would prefer not to dive into use of any jQuery or javascript as I am in the process of learning ASP.NET MVC, and would want to know why the approach I took is not working? The second answer by Dennis, in the post that I referenced also suggested similar approach.
Could someone kindly tell me what I am doing wrong?
Thanks
This is just an example how you can load view from AJAX without page refresh, it may help you.
It send text value to controller by ajax call and load that value in other view which replace main view, if you don't want to replace main view then you can take other div instead same div to load content.
Controller:
public ActionResult Index()
{
return View();
}
[HttpPost]
public PartialViewResult TestAjax(string Name)
{
ViewBag.Name = Name;
return PartialView();
}
Index.cshtml:
<input type="button" id="btnSearch" class="btn btn-warning" style="height:35px;width:120px" value="Search"/>
<label>Name:</label><input type="text" id="txtName" name="txtName" />
<script>
$('#btnSearch').click(function () {
$.ajax({
url: '#Url.Action("TestAjax", "Home")',
data: { Name: $("#txtName").val() },
type: 'POST',
success: function (data) {
$("#divContent").html(data);
}
});
});
</script>
TestAjax.cshtml:
#ViewBag.Name
As #StephenMuecke pointed out in his comments, the libraries not being loaded correctly was the problem. While creating a new bundle of all libraries and adding it in the BundkeConfig.cs I had missed ~/Scripts/jquery.unobtrusive-ajax.js*. Got it working now.

Passing hidden value to controller (asp.netmvc)

Trying to pass a value with Ajax.Beginform but not working for some reason.
What I’m doing:
I’m making an ajax call which returns an id and replaces a hidden element.
Ajax: Ajax.BeginForm("Action1", "Controller1", new AjaxOptions { InsertionMode
= InsertionMode.Replace, UpdateTargetId = "pageId" })
Hidden Element (which is outside of the above Ajax.BeginForm):
<input type="hidden" name="pageId" id="pageId" value=""/>
Now, I want to use that pageId (in the hidden value) and pass it to another action, using another Ajax.BeginForm.
Ajax.BeginForm("Action2", "Controller1”))
{
<input type="hidden" name="pageId" id="pageId" value=""/>
<input type="submit" />
}
The controller Action2 looks like this:
public void Action2(string pageId)
{
}
But this is not working obviously. What are your suggestions?
I think that i understand your problem what you are facing. Please correct me if i am wrong.
First Ajax call which will set your pageid
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
#using (Ajax.BeginForm("Foo", "FooController", new AjaxOptions {
HttpMethod = "Post",
OnSuccess = "success"
}))
{
<input type="submit" value="Save" id="btnsubmit" />
}
[HttpPost] // you said you return a string here
public string Foo()
{
return "1";
}
<script type="text/javascript">
function success(result) {
$('#pageId').val(result);
}
</script>
secondly here is the place where your pageid will be set. when you will press the submit button below the set value will be posted to the controller.
#using (Ajax.BeginForm("Foo1", "FooController", new AjaxOptions { OnSuccess = "HandlePostback" }))
{
<input type="hidden" name="pageId" id="pageId" />
<input type="submit" value="Save" id="btnsubmit" />
}
[HttpPost]
public ActionResult Foo1(int pageId)
{
return View();
}

Open Telerik Window

I hope you can assist me with one dillema. I´m going to write a bunch of code before I ask my question below :)
When something is clicked on my page:
<input type='button' value='1' name='derp1' onclick='OpenTelerikWindow(1)' />
<br/>
<input type='button' value='2' name='derp2' onclick='OpenTelerikWindow(2)' />
I open Telerik Window with Jquery:
function OpenTelerikWindow(arg) {
var url = '/Controller/Derp/';
$.ajax({
type: "GET",
url: url,
dataType: "html",
data: { id: arg }
success: function (data) {
$('#PaymentWindow').data("tWindow").content(data);
$('#PaymentWindow').data("tWindow").center().open().refresh();
}
});
}
My Controller ActionResult:
public ActionResult Derp(int id)
{
SomeModel someModel = _GetModel(id);
return PartialView("Derp", someModel)
}
And then the content of my Telerik Window goes something like this:
#SomeModel
<div id="theDerpina">
<div>
//Some Stuff
#using (Ajax.BeginForm("Derpina1", "Controller", new { id = SomeModel.id }, new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "theDerpina",
InsertionMode = InsertionMode.Replace
}, new { id = "feedback-form" }))
{
//Some Stuff
<button type="submit" > Submit</button>
<br/>
<button type="button" > CloseWindow </button>
}
</div>
<div>
//More Stuff
#using (Ajax.BeginForm("Derpina2", "Controller", new { id = SomeModel.id }, new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "theDerpina",
InsertionMode = InsertionMode.Replace
}, new { id = "feedback-form" }))
{
//Different Stuff
<button type="submit" > Submit</button>
<br/>
<button type="button" > CloseWindow </button>
}
</div>
</div>
My two other Controller Actions:
public ActionResult Derpina1(int id)
{
SomeModel someModel = _GetModel(id);
if(ModelState.IsValid)
{
//DoStuff
return View("SomeOtherView");
}
else
{
return PartialView("Derp", someModel);
}
}
public ActionResult Derpina2(int id)
{
SomeModel someModel = _GetModel(id);
if(ModelState.IsValid)
{
//DoDifferentStuff
return View("SomeOtherView");
}
else
{
return PartialView("Derp", someModel);
}
}
When I open the Window once, everything works fine. However if I were to open the Window, close it, and then open it again then weird things happen. Let´s say for instance that I clicked the submit button for Derpina1, I would receive two calls to that particular Controller action. If I monitor the console in Firebug I see two separate calls to my controller action. Then the same thing would happen if I would close the Window one more time, open it again, and submit again, my controller action would now receive 4 calls to my controller action.
Perhaps you guys can point to the right direction. Should I open the Telerik Window in a different way, also should I use different method to return ModelError were that to happen? (because I´m faced with the same behaviour if I get a ModelError)
I managed to find out the solution after googling a while. All I did was creating a Window on the fly from within the script, and then destroying it after I have used it, like so:
function OpenTelerikWindow(arg) {
var url = '/Controller/Derp/';
$.ajax({
type: "GET",
url: url,
dataType: "html",
data: { id: arg }
success: function (data) {
var paymentWindow = $("<div id='PaymentWindow'></div>").tWindow({
title: "Payment",
contentUrl: '',
html: data,
modal: true,
resizable: false,
draggable: true,
width: 500,
height: 640,
onClose: function (e) {
e.preventDefault();
paymentWindow.data('tWindow').destroy();
}
});
paymentWindow.data('tWindow').center().open();
}
});
}

MVC3 Razor Ajax Form Submit

I use The MVC3 Helper to generate my Ajax form like this:
#using (Ajax.BeginForm("Attended", "Lesson", new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "mdl" + item.ID
}))
{
#Html.HiddenFor(modelItem => item.ID);
#Html.CheckBox("Attended", item.Attended, new { OnChange = "javascript:this.form.submit()"});
}
I just don't find the proper way to submit the Form on the change event of the checkbox.
I don't want my users to click the submit button.
The HTMLAttribute works, but on the change a postback happens instead of an ajax request.
Does anybody know the answer?
First, create a submit button inside your form, and hide it by setting the attribute style="display:none;". Then, instead of using this.form.submit() in your onchange event, use the following:
$(this).parents('form:first').find(':submit')[0].click();
This will invoke the jquery.unobtrusive-ajax.js script, and complete your Ajax submission.
this may help
#Html.CheckBox("Attended", item.Attended, new { OnChange = "submitForm"});
function submitForm(e)
{
document.forms[0].submit();
}
What about using jQuery to trigger the submit? Like in this answer How to post ASP.NET MVC Ajax form using JavaScript rather than submit button
Using the .change() event instead of the .click() event the jQuery part would look something like this:
$(function() {
$('form#ajaxForm').find('input.submit').change( function() {
$('form#ajaxForm').trigger('submit');
});
}
#using (Ajax.BeginForm("Attended", "Lesson", new { id = Model.Id }, new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "mdl" + item.ID
}, new { id = "ajaxForm" } ))
{
#Html.HiddenFor(modelItem => item.ID);
#Html.CheckBox("Attended", item.Attended, new { #class = "submit"});
}
This is totally untested code so beware of typos :)
Forms are the classical way of sending a request - therefore it is POST - your GET setup is overruled by that in onChange - submits will always clear the content and replaced with server content - i do some javascript to send using AJAX - cannot see that, so I presume that it does exactly that. your OnChange should execute this AJAX function instead ...
Hmm, what actually worked for me, even on cell phones, which was a problem area, was the following, in my cshtml file for a Partial View. It also includes code to grey out the button and write "Saving..." until the view posts back, which avoids people pounding on the submit button when they get impatient for slow SQL Servers.
<div id="myFutureDayEdit">
<script type="text/javascript">
$(document).ready(function () {
$("#submitFutureDayEditVisibleButton").click(function () {
$(this).prop('disabled', true);
$("#myUserMessage").html("Saving...");
$("#myUserMessage").show();
document.getElementById("submitFutureDayEditHiddenButton").click();
});
});
</script>
#Html.ValidationSummary(true)
#using (Ajax.BeginForm("SaveFutureDayEdit", "Member", new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "myFutureDayEdit" }))
{ ... bla bla bla
and
<input id="submitFutureDayEditVisibleButton" type="button" value="Save Changes" />
<input id="submitFutureDayEditHiddenButton" style="display:none;" type="submit" value="SC" />
<div id="myUserMessage">
#if (Model.UserMessage != null)
{ #Model.UserMessage }
</div>
<input type="hidden" id="bUnsavedChanges" name="bUnsavedChanges" value="false" />
}
</div>
<div id="hahuloading">
<div id="hahuloadingcontent">
<p id="hahuloadingspinner">
Saving...
</p>
</div>
</div>

Resources