I'm using jQuery AutoComplete, and I have an auto-complete search box to search for users.
Default.aspx
<script type="text/javascript" language="javascript">
$(document).ready(function() {
$("#<%= txtUser.ClientID %>").autocomplete('UsersAutoComplete.ashx');
});
</script>
<asp:TextBox ID="txtUser" runat="server" />
UsersAutoComplete.ashx
public class UsersAutoComplete : IHttpHandler
{
public void ProcessRequest (HttpContext context)
{
List<User> users = DataContext.Users
.Where(u => u.Username.StartsWith(context.Request.QueryString["q"]))
.Take(Int32.Parse(context.Request.QueryString["limit"]))
.OrderBy(u => u.Username)
.ToList();
foreach (User user in users)
{
context.Response.Write(user.Username + Environment.NewLine);
}
}
public bool IsReusable
{
get { return false; }
}
}
As you can see, it only returns the Username. I'd also like to return the user's UserID as well.
The results will still only show a list of Usernames, but when someone selects a user, I'd like to store the UserID for that user in a hidden value so that I can do whatever I need to with it. I'll be running a query on the selected user, and I'd rather lookup the user by UserID than by Username.
Is there a way to do this?
I would create a class that contains the values you want returned. Then create a new instance of that class with the values and serialize the response using JSON.
That should be enough to get you pointed in the right direction.
EDIT: Here is how I do it.
$("#<%= txtUser.ClientID %>").autocomplete(
{
source: function (request, response) {
$.ajax(
{
url: autocompleteSourceUrl,
dataType: "json",
type: "POST",
data: { LookupPrefix: request.term, TotalResults: 10 },
success: function (data) {
response($.map(data.LookupItems,
function (item) {
var itemLabel = item.DisplayName;
if (itemLabel.length > 37)
itemLabel = itemLabel.substring(0, 37) + "...";
return { label: itemLabel, value: item.DisplayName, data: item }
}))
}
});
},
minLength: 3,
select: function (event, ui) {
selectedItemData = ui.item.data;
}
});
This is how I setup the autocomplete with the custom class returned. My class being returned has the following structure:
{ Id: int, DisplayName: string }
Notice also the select function. That stores an internal reference to the data item that was returned. So when I need to submit that info I can just look at the selectedItemData and use all the properties of the class at that time as well.
I hope this helps a little more. But the part for you to work with would be in the success method where I assign the object to the item.
Related
I have a controller that applies to an edit view in asp.net MVC. I have an actionlink that sends the row Id to the controller which then brings back the correct row to see in the associated view.
I then have a partial view below that. That also requires a parameter in order to bring associated data from another table.
I have a Jquery .post call that runs after the page is loaded. I can alert out and show the exact value I want to send to the controller.
$(document).ready(function () {
var url = "/Home/MmsAndNotes";
var Uc = $("#Id").serialize();
alert(Uc);
$.post(url, {Id: Uc}, function (data) {
alert("what is Uc now? " + uc); //just for testing
});
})
I have also used it this way.
$(document).ready(function () {
var url = "/Home/MmsAndNotes";
var Uc = $("#Id").val();
alert(Uc);
$.post(url, Uc, function (data) {
});
})
the alerts come up and show the value I want. However, when the .post call runs, it sends a null value. Here is my controller.
public ActionResult MmsAndNotes(string Id)
{
//Declare LogisticsVM for individual policy info
LogisticsMMS_NotesVM model;
if(uc == null)
{
return Content("uc is empty.");
}
int val = Convert.ToInt32(uc);
using (Db db = new Db())
{
LogisticsMMS_NotesDTO dto = db.LogisticsMMS.Find(val);
//confirm policy exists
if (dto == null)
{
return Content("This policy cannot be found." + val);
}
model = new LogisticsMMS_NotesVM(dto);
}
return PartialView(model);
}
It always returns as uc is empty. I repeat, when the alerts come up. I get the correct value to send to the controller. But once it sends, something happens and it converts to null. HELPPPPP.. please .. I'm losing my mind over this one.
I don't know why, but changing my $.post() call to an $.ajax({}) call solved the issue. As you can see above, I had the $.post call. Using this instead,
$.ajax({
type: "POST",
url: "/Home/MmsAndNotes",
dataType: 'text',
data: { Id: Uc }
});
Solved it. I thought Jquery's shortened calls worked the same way. They certainly might, but doing it this way was the only way it worked for me.
P.S. Thanks Tyler (above) for your comments.
this solution should be work :
$(document).ready(function () {
$.ajax({
url: '/Home/MmsAndNotes',
type: 'GET',
dataType: "html",
data: { uc : $("#Id").val() },
success: function (result) {
code here
}
});
})
You need to verify if $("#Id").val() is not empty
I have a method in the controller that return a ViewBag with Json.
public JsonResult FilterCheck(int id, int[] mycheck, string idprot)
{
ViewBag.Utenti = this.GetDbContext().utente.Include(s => s.cod_servizio_utente).Where(x => x.cod_servizio_utente.Select(l => l.id).Contains(5)).ToList();
return Json(ViewBag.Utenti, JsonRequestBehavior.AllowGet);
}
In the view I have this script function ajax, if this function have "success" i would refresh a div that include a foreach on the viebag.Utenti:
$.ajax({
type: "POST",
url: "#Url.Action("FilterCheck","Operatore")",
datatype: "json",
traditional: true,
data: { 'mycheck': mycheck, 'idprot': idprot, 'id': '#Model.id' },
success: function(data) {
var html = $(data).filter('#external-events').html();
$('#external-events').html(data);
}
});
<div id='external-events'>
#foreach (HAnnoZero.Repositories.utente item in ViewBag.Utenti)
{
<div class='col-lg-3'><div class='external-event'>#item.id- #item.cognome #item.nome</div></div>
} </div>
But dont work. How can do for refresh the foreach inside div id "external events"?Who could help me?
Firstly you do not need to assign the collection to ViewBag
public ActionResult FilterCheck(int id, int[] mycheck, string idprot)
{
var data = this.GetDbContext().utente.Include(......
// Build anonymous object collection to avoid circular reference errors
var response = data.Select(d => new
{
id = d.id,
cognome = d.cognome
// other properties as required
});
return Json(response);
}
Secondly you are returning JSON, not html, so in your success function you need to iterate through the properties and build your html (not sure what your properties are, so adjust as necessary)
success: function(data) {
$('#external-events').empty(); // clear existing items
$.each(data, function(index, item) {
var div = $('<div><div>'); // Create new element
div.text(item.id + ' ' + item.cognome); // Set inner text
$('#external-events').append(div); // add the new element
});
}
An alternative is to have the action method return a partial view containing the html and then use
success: function(data) {
$('#external-events').html(data);
}
I have a webform with few textboxes and dropdownlists, and a submit button
when the user clicks the submit button im sending the form values to the controller with an ajax call and from controller to model to database
after submitting the form values are still being displayed in the respective textboxes.
i also have a output parameter with my procedure, if the data is successfully submitted then i will get output parameter value as 1 else 0
so based on this output parameter value from the controller i should be able to clear the form values, if the insertion fails the values should be displayed
how to achieve it?
<script type="text/javascript">
function CreateUser() {
$.ajax({
url: '#Url.Content("~/User/CreateUser")',
data: { My Data },
type: 'GET',
success: function (data) {
alert(data);
}
});
}
$('#btnCreate').click(function () {
CreateUser();
});
</script>
Code:
public ActionResult RegisterUser(Users objUser)
{
//i have done some code here to bind dropdownlists from database etc
return View(objUser);
}
public ActionResult CreateUser(str Uname)
{
try
{
Users objUser = new Users();
int Successval = objUser.CreateUser(Uname);
}
catch (Exception ex)
{
}
return RedirectToAction("RegisterUser");
}
try this ...
after you get value 0 then just call below line
document.getElementById("YOUR_FORM_ID").reset();
Update
View :
<form id="myform">
...
</form>
Javascript :
function CreateUser() {
$.ajax({
url: '#Url.Content("~/User/CreateUser")',
data: { My Data },
type: 'GET',
success: function (data) {
if(data == 0)
{
document.getElementById("myform").reset();
}
}
});
}
I'm having a lot of trouble making jQuery's autocomplete widget work for me. I am using a list of key/value pairs from a server.
I have the following requirements:
If the user set the id of the value, like he knowes the code of the city
and instad of typing the name of a city he put the code of the city-- I want that the autocomplete will put the name of the city, and it dosn't!!
I edit My Code, now it works!
I add this lines
if (data.d.length == 1 && request.term.match(/\d+/g))
SetValue(textbox, hidden, data.d[0]);
else
and the function function SetValue(textbox, hidden, value){
textbox.focus().val(value.Text);
hidden.val(value.Semel);}
Another thing is if one is using the same page for creation and editting - on reloading the page while editting, you have to recreate all the spans etc for the values, and I want to send from the server just the code of the autocomplete, not the text value, and I want when i will set the value into the textBox, the autoComplete will start to work and will bring the value from the server
But with this I get still stuck:
I Dont know how to trigger the “autocomplete” event with send the value (the request value)
Here is My C# code:
[WebMethod(EnableSession = true)]
[ScriptMethod]
public List<IEntityBase> FetchList(string Text, string Code, string Dspl, int NumRecordes, string TableName)
{
Text = Server.UrlDecode(Text);
List<Tavla> tvListById = null;
int ignored = 0;
if (int.TryParse(Text, out ignored))
tvListById = TvList.GetTvListById(TableName, ignored, Code, Dspl);if (tvListById != null && tvListById.Count != 0)
return tvListById.Cast<IEntityBase>().ToList();
var fetchShem = TvList.GetData(TableName, Code, Dspl)
.Where(m => m.Shem.ToLower().Contains(Text.ToLower()))
.Take(NumRecordes);
return fetchShem.Cast<IEntityBase>().ToList();
}
and here is my Jquery Code:
enter code here
textbox.autocomplete({
source: function (request, response) {
$.ajax({
url: "AutoComplete.asmx/" + funcName,
data: "{ 'Text': '" + escape(request.term) + "','Code':'" + code + "','Dspl':'" + dspl + "','NumRecordes':'" + numrecordes + "','TableName':'" + tablename + "'}",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
if (data.d.length == 1 && request.term.match(/\d+/g))
SetValue(textbox, hidden, data.d[0]);
else
response($.map(data.d, function (item) {
return {
label: item.Text,
value: item.Semel
}
}));
}
},
error: function (msg) { alert(msg); }
});
},
minLength: minLength,
select: function (event, ui) {
var selectedObj = ui.item;
if (selectedObj) {
textbox.val(selectedObj.label);
hidden.val(selectedObj.value);
} return false; },
});function SetValue(textbox, hidden, value) {
textbox.focus().val(value.Text);
hidden.val(value.Semel);
}
For your first question, it all depends the logic you have tried , just in case if you have an id for any country then this shouldnt be any difficult.
Second query is all about performance of the page, this also shouldnt be any tougher if you try updating the elements based on the search pattern using ajax, where in you have to update just the realted elements,while keeping rest of your Page intact .
refer http://jquery.com/ for better understanding of the same
I'm trying to use the autocomplete widget in jQuery however when I start typing nothing shows up below it. I can tell it's doing something becasue as I type I can see the scroll bar on the page changing as the list gets shorter, but I can't see the results. My code is below. Any help is appreciated with this.
My controller method looks like this:
public ActionResult GetUsers(string query)
{
var empName = from u in HomeModel.CombineNames()
where u.StartsWith(query)
select u.Distinct().ToArray();
return Json(empName);
}
My View looks like this:
<script type="text/javascript">
$(document).ready(function() {
$("input#autocomplete").autocomplete({
source: function(request, response) {
$.ajax({
url: '/Home/GetUsers',
type: "POST",
dataType: "json",
data: { query: request.term },
success: function(data) {
response($.map(data, function(item) {
return { label: item, value: item };
}));
}
});
}
});
})
</script>
<input type="text" id = "autocomplete"/>
You are missing a few things, like render item, cache managment.
the code should looks something like this: (assuming your action return an array of string)
var cache = {},lastXhr;
$( "input#autocomplete" ).autocomplete({
minLength: 4,
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
var descripcion = new Array();
peticion = $.getJSON('/Home/GetUsers',{ query: request.term }, function (data, status, xhr) {
for (d in data) {
descripcion.push(data[d]);
}
cache[term] = descripcion;
if (xhr === peticion) {
response(descripcion);
}
});
},
select: function( event, ui ) {
$("input#autocomplete" ).val( ui.item);
return false;
}
})
.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item + " </a>" )
.appendTo( ul );
};
Try using the inspection tools of your browser to examine the area where your scroll bar is changing. If the elements are present, you likely need to make some changes to the CSS so your text color is different from the background color (or some other display-related issue).