I have problem with my ajax-search. When I adding to my model some data, I go to my Index view, where I use my ajax-search. And then I erase text from input and submit form, Index view did not show added data. How to fix that??
It's my SearchController
public ActionResult Index(string searhcString)
{
var competitions = from s in db.Competitions
select s;
if(!String.IsNullOrEmpty(searhcString))
{
competitions =competitions.Where(s => s.CompName.ToUpper().Contains(searhcString.ToUpper())
|| s.CompName.ToUpper().Contains(searhcString.ToUpper()));
}
return View(competitions);
}
Index View
#using (Ajax.BeginForm("AjaxSearch", "Competitions",
new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "ajaxTable"
}))
{
<input type="text" name="q" />
<button type="submit"><img height="10" src="#Url.Content("~/Images/findBtn.png")" /></button>
}
In internet Explorer ajaxs calls are cached by default... may be this is your case.
You can disable this globally this way:
$.ajaxSetup ({
// Disable caching of AJAX responses
cache: false
});
Or you can disable it just in this case adding cache: false in your AjaxOptions
Behind scene, this will append a timestamp to each call making it different from previous and that way preventing caching.
If this solves your issue, your could do something similar but sending a checksum of the value of your fields (instead of a timestamp)... this way, the post is only done when the filter/search options indeed changed.
Related
I have a form which is used to create a resource, and it has two fields to be populated. When a user enters a value into the first field, I want to automatically call back to an action method on the server which will determine the value to use in the second field, without the user having to submit the form.
For example:
Full Name - User enters this value
Username - View calls server with the value specified in Full Name, server calculates value to be used, server passes value back to view, view presents the value.
Is it possible to do this in MVC core, and if so, can you please point the right direction?
I've been reading up on remote validation, and feel that I could probably use (or abuse) it in order to achieve the functionality looking for, but I'd imagine there's a property way to do this.
Any pointers appreciated.
Remote Validation can only do the validation without submitting the form, but It can't assign value to another field. In your case. It's actually very simple. You can use the js onchange event listen to the first field, in the event, use ajax to access the background. and then fill the returned value into the second field in the callback function. Below is a simple test
View:
<span>Full Name</span>
<input type="text" id="FullName" name="FullName" />
<span>User Name</span>
<input type="text" id="UserName" name="UserName" />
#section scripts{
<script>
$("#FullName").on("change", function () {
$.ajax({
type: "post",
url: "/User/GetUserName",
data: {
fullname: $("#FullName").val()
},
success: function (result) {
$("#UserName").val(result);
}
})
})
</script>
}
Controller:
[HttpPost]
public string GetUserName(string fullname)
{
var username = fullname.Split(" ");
return username.First();
}
Result:
#mj1313's answer was extremely helpful, but I didnt like the idea of having some loose Javascript kicking around in my views, especially since I may need to use this same functionality in multiple views.
I ended up converting the script into a global function, and calling it from within the onchange event like so.
JS Function
(in site.js)
function fullNameToUserName (fullNameId, usernameId) {
$.ajax({
type: "get", // GET rather than POST
url: "/User/GetUserNameFromFullName",
data: {
fullname: $(fullNameId).val()
},
success: function (result) {
$(usernameId).val(result);
}
})
}
Action method
[HttpGet("GetUserNameFromFullName")] // GET rather than POST
public IActionResult GetUserNameFromFullName(string fullName)
{
var username = fullName.Split(" ");
return Ok(username.First());
}
Model
public class UserModel
{
public string FullName { get; set; }
public string Username { get; set; }
}
View
#model MvcApp.Models.UserModel
#Html.DisplayNameFor(m => m.FullName)
#Html.TextBoxFor(m => m.FullName, new
{
onchange = $"fullNameToUserName({#Html.IdFor(m => m.FullName)}, {#Html.IdFor(m => m.Username)});"
})
#Html.DisplayNameFor(m => m.Username)
#Html.TextBoxFor(m => m.Username)
The only problem I have with this approach is that the call to fullNameToUserName(fullNameId, usernameId) is not strongly-typed, and if this function is called from multiple views, it's likely to be miss-typed at some point.
While #mj1313's answer was great and pointed me in the right direction, I wasn't fully satisfied with the approach. Personally, I prefer this approach as it's slightly more reusable and keeps my view's more lean.
Below Mention is the paging i have done using MVC PageList on my partial view and also i have one submit button on my partial view
Controller
var model1 = PrepareTestModel((int)_studAnsdal.Test_Id, Page);
ViewBag.TestId = TestId;
Page++;
return PartialView("_studentPartial", model1.OrderByDescending(v => v.Question_Id).ToPagedList(Page, 1));
View
<input type="submit" Value="Submit Answer" id="abc">
<div class="pagedList">
#Html.PagedListPager(Model, page => Url.Action("TestPaging", "Student", new { page=ViewBag.page, TestId = ViewBag.TestId }), PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new AjaxOptions { UpdateTargetId = "results", HttpMethod = "POST" }))
</div>
What i want to do is whenver user click on submit i want to shift my paging value to the next page that is one increment to it but i m not getting it done as page value is passed using query string any help is appreciated
In my mvc4 application i want to use html.beginform() to pass multiple parameters to an actionResult on the same controller.
I do it like this:
view:
<div>
#using (Html.BeginForm("AddNote", "Lead",FormMethod.Post, null))
{
#Html.Hidden("leadID",#Model.ID)
<input type="text" name="noteBody" />
<input type="submit" class="mainButton" value="Add New!"/>
}
</div>
Controller (LeadController):
[HttpPost]
ActionResult AddNote(int leadID, string noteBody)
{
Note note = new Note();
note.DateModified = DateTime.Now;
note.Title = "No Title";
note.Body = noteBody;
Lead lead = unitOfWork.LeadRepository.GetById(leadID);
lead.Notes.Add(note);
unitOfWork.Save();
return RedirectToAction("Details", new { id = leadID });
}
when i press the submit button i get an exception:
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Lead/AddNote
this is the place to say that i have tried it withput parameters and it worked just fine.
I've also tried to pass the "leadID" parameter inside the form declaration (new {leadID = #Model.ID}).
Any idea what am i doing wrong ?
Just add the 'public' modifier to your action and it will do the magic.
The AddNote method should be public. Use the public keyword and it will work.
Add the HTTPPOST attribute , like this
[HttpPost]
ActionResult AddNote(int leadID, string noteBody)
{
Note note = new Note();
note.DateModified = DateTime.Now;
note.Title = "No Title";
note.Body = noteBody;
Lead lead = unitOfWork.LeadRepository.GetById(leadID);
lead.Notes.Add(note);
unitOfWork.Save();
return RedirectToAction("Details", new { id = leadID });
}
Perhaps it helps you
In my application I need to pass some values from one page(page A to Page B) to another page.
For this I am using Session variables(I cannot use Tempdata as it doesn't work on loadbalancing).
In Page A I am setting the Session Variable.
In Page B I need to retrieve the above Session variable.
For this I am using a Hidden field in Page B.
I dont know how to set the Session Variable to Hidden Field in Page B.
Page A
[HttpPost]
public JsonResult GetFileName(string updatedfileName, string orgfileName)
{
Session["OrgFileName"] = orgfileName;
Session["UpdatedFileName"] = updatedfileName;
var result = myService.getFile(updatedfileName, orgfileName);
return Json(result, JsonRequestBehavior.AllowGet);
}
Page B
<div style="display:none" >
<input type="hidden" value="" id="hdnfilename" />
</div>
In the controller of "Page B", set a ViewBag.MyValueto your session variable and apply it to the hidden's value.
Controller
ViewBag.MyValue = Session["MYVALUE"];
View
<input type="hidden" value="#ViewBag.MyValue" id="hdnfilename" />
If you need to get a session variable from JavaScript, you will need to develop an action that will return the session variable and consume it with JavaScript/jQuery, like this:
// Controller code
[HttpGet]
public JsonResult GetSessionVarValue(string key)
{
return Json(new { key = key, value = Session[key] }, JsonRequestBehavior.AllowGet);
}
// JavaScript code
var mySessionValue;
$.getJSON("/GetSessionVarValue", "MYKEY", function(data) {
mySessionValue = data.value;
});
You may take care with Session variables in load balance, too. The best way to secure store session variables is changing the state of session mode configuration to StateServer. http://msdn.microsoft.com/en-us/library/ms178586.aspx
For an implementation of Magnific Popup, I need to pass a post id to the ajax settings. The post id is stored in a data attribute of the element to which Magnific Popup is bound. I would like this to work:
html element:
<a data-id="412">Clicke me</a>
Javascript:
$('.element a').magnificPopup({
type: 'ajax',
ajax: {
settings: {
url: php_array.admin_ajax,
type: 'POST',
data: ({
action:'theme_post_example',
id: postId
})
}
}
});
Where postId is read from the data attribute.
Thanks in advance.
$('.element a').magnificPopup({
callbacks: {
elementParse: function(item){
postData = {
action :'theme_post_example',
id : $(item.el[0]).attr('data-id')
}
var mp = $.magnificPopup.instance;
mp.st.ajax.settings.data = postData;
}
},
type: 'ajax',
ajax: {
settings: {
url: php_array.admin_ajax,
type: 'POST'
}
}
});
Here is how to do it:
html:
<a class="modal" data-id="412" data-action="theme_post_example">Click me</a>
jquery:
$('a.modal').magnificPopup({
type: 'ajax',
ajax: {
settings: {
url : php_array.admin_ajax,
dataType : 'json'
}
},
callbacks: {
elementParse: function() {
this.st.ajax.settings.data = {
action : this.st.el.attr('data-action'),
id : this.st.el.attr('data-id')
}
}
},
parseAjax: function( response )
{
response.data = response.data.html;
}
});
php
function theme_post_example()
{
$id = isset( $_GET['id'] ) ? $_GET['id'] : false;
$html = '<div class="white-popup mfp-with-anim">';
/**
* generate your $html code here ...
*/
$html .= '</div>';
echo json_encode( array( "html" => $html ) );
die();
}
As this answer was the original question regarding inserting data into Magnific's ajax call, I'll post this here.
After many hours of trying to figure this out, you should know that if you're using a gallery with the ability to move between gallery items without closing the popup, using elementParse to set your AJAX data will fail when you visit an item after already viewing it (while the popup is still open).
This is because elementParse is wrapped up in a check that it makes detect if an item has already been 'parsed'. Here's a small explanation as to what happens:
Open gallery at item index 2.
Item has not been parsed yet, so it sets the parsed flag to true and runs the elementParse callback (in that order). Your callback sets the ajax options to fetch this item's data, all is well.
Move (right) to item index 3.
Same as above. The item has not been parsed, so it runs the callback. Your callback sets the data. It works.
Move (left) back to item index 2.
This time the item has been parsed. It skips re-parsing the item's element for assumed potential performance reasons.Your callback is not executed. Magnific's ajax data settings will remain the same as if it were item index 3.
The AJAX call is executed with the old settings, it returns with item index 3's data instead, which is rendered to the user. Magnific will believe it is on index 2, but it is rendering index 3's data.
To resolve this, you need to hook onto a callback which is always executed pre-ajax call, like beforeChange.
The main difference is that the current item isn't passed through into the callback. Fortunately, at this point, magnific has updated their pointers to the correct index. You need to fetch the current item's element by using:
var data = {}; // Your key-value data object for jQuery's $.ajax call.
// For non-closures, you can reference mfp's instance using
// $.magnificPopup.instance instead of 'this'.
// e.g.
// var mfp = $.magnificPopup.instance;
// var itemElement = mfp.items[mfp.index].el;
var itemElement = this.items[this.index].el;
// Set the ajax data settings directly.
if(typeof this.st.ajax.settings !== 'object') {
this.st.ajax.settings = {};
}
this.st.ajax.settings.data = data;
This answer can also be used as a suitable alternative to the currently highest voted, as it will work either way.
You may use open public method to open popup dynamically http://dimsemenov.com/plugins/magnific-popup/documentation.html#public_methods
postId = $(this).attr('data-id')
$(this) retrieve the current element (the link you clicked on), and attr the value of the specified attribute.