I am using ASP.NET MVC3 with EF Code First. I have not worked previously with jQuery. I would like to add autocomplete capability to a dropdownlist that is bound to my model. The dropdownlist stores the ID, and displays the value.
So, how do I wire up the jQuery UI auto complete widget to display the value as the user is typing but store the ID?
I will need multiple auto complete dropdowns in one view too.
I saw this plugin: http://harvesthq.github.com/chosen/ but I am not sure I want to add more "stuff" to my project. Is there a way to do this with jQuery UI?
Update
I just posted a sample project showcasing the jQueryUI autocomplete on a textbox at GitHub
https://github.com/alfalfastrange/jQueryAutocompleteSample
I use it with regular MVC TextBox like
#Html.TextBoxFor(model => model.MainBranch, new {id = "SearchField", #class = "ui-widget TextField_220" })
Here's a clip of my Ajax call
It initially checks its internal cached for the item being searched for, if not found it fires off the Ajax request to my controller action to retrieve matching records
$("#SearchField").autocomplete({
source: function (request, response) {
var term = request.term;
if (term in entityCache) {
response(entityCache[term]);
return;
}
if (entitiesXhr != null) {
entitiesXhr.abort();
}
$.ajax({
url: actionUrl,
data: request,
type: "GET",
contentType: "application/json; charset=utf-8",
timeout: 10000,
dataType: "json",
success: function (data) {
entityCache[term] = term;
response($.map(data, function (item) {
return { label: item.SchoolName, value: item.EntityName, id: item.EntityID, code: item.EntityCode };
}));
}
});
},
minLength: 3,
select: function (event, result) {
var id = result.item.id;
var code = result.item.code;
getEntityXhr(id, code);
}
});
This isn't all the code but you should be able to see here how the cache is search, and then the Ajax call is made, and then what is done with the response. I have a select section so I can do something with the selected value
This is what I did FWIW.
$(document).ready(function () {
$('#CustomerByName').autocomplete(
{
source: function (request, response) {
$.ajax(
{
url: "/Cases/FindByName", type: "GET", dataType: "json",
data: { searchText: request.term, maxResults: 10 },
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data, function (item) {
return {
label: item.CustomerName,
value: item.CustomerName,
id: item.CustomerID
}
})
);
},
});
},
select: function (event, ui) {
$('#CustomerID').val(ui.item.id);
},
minLength: 1
});
});
Works great!
I have seen this issue many times. You can see some of my code that works this out at cascading dropdown loses select items after post
also this link maybe helpful - http://geekswithblogs.net/ranganh/archive/2011/06/14/cascading-dropdownlist-in-asp.net-mvc-3-using-jquery.aspx
Related
I would like to ask You for help mi to figure it out, how to use result of first Complete which is giving me a client number as #select_client_id in another autocomplete.
At one page, i'm selecting order from autocomplete list:
$( function() {
$( "#select_order" ).autocomplete({
source: function( request, response ) {
$.ajax({
url: "data/orderData.php",
type: 'post',
dataType: "json",
data: {
find_order_out: request.term
},
success: function( data ) {
response( data );
}
});
},
select: function (event, ui) {
$('#select_order').val(ui.item.label); // display the selected text
$('#select_order_id').val(ui.item.value); // save selected id to input
$('#select_client_id').val(ui.item.client_id);
return false;
}
});
});
Then there is another input field which is selecting packages for this order, where i`m using a client id, from first autocomplete:
$("#select_package").autocomplete({
source: function( request, response ) {
$.ajax({
url: "data/orderData.php",
type: 'post',
dataType: "json",
data: {
find_client_package_on_storage: request.term, client: client
},
success: function( data ) {
response( data );
console.log(client);
}
});
},
select: function (event, ui) {
$('.select_package').val(ui.item.label);
$('.select_package_id').val(ui.item.value);
return false;
}
});
For now, i've got only one client, so variable is declared by:
<script>
client="1";
</script>
How can i do it properly? :)
Well, it takes a little bit longer than normally, but it wasn't priory to figure it out :)
Answer is very simple :)
In #select_order autocomplete, i've add:
select: function (event, ui) {
$('#select_order').val(ui.item.label);
$('#select_order_id').val(ui.item.value);
$('#select_client_id').val(ui.item.client_id);
client_number=$("#select_client_id").val();
return false;
And at the end of body set a variable declaration:
<script>
let client_number = 0;
</script>
That solved my problem :)
I am using a kendo multiselect widget for users to select different values pulled from the database via an ajax call. The ajax call takes one parameter, searchValue, which will narrow down the returned data. Here is my controller:
[HttpPost]
public JsonResult ProfitabilitySearch(string searchValue)
{
return Json(InventoryDataAccess.ProfitabilitySearch(searchValue));
}
1) How do you get the value from the text box to use as your searchValue? I commented the area in question below.
Here is my dataSource:
var searchDataSource = new kendo.data.DataSource({
transport: {
read: function () {
$.ajax({
type: 'POST',
url: Firm.ProfitabilitySearchURL,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
//'SuperClient' is test data to see if it works, but what do i
//need to make searchValue = what I type?
data: JSON.stringify({ searchValue: 'SuperClient'}),
success: function (data) {
return data.RESULT;
}
});
}
},
group: { field: 'category' },
serverFiltering: true
});
And here is where I create the multiselect widget:
var TKSearch = $("#TKSearch").kendoMultiSelect({
dataSource: searchDataSource,
autoBind: false,
minLength: 3,
placeholder: 'Search Timekeepers...',
dataTextField: 'label',
dataTextValue: 'value',
delay: 200
}).data("kendoMultiSelect");
I'm not sure if this will help, but here is the structure of the json that is returned from the ajax call:
{"label":"SUNFLOWER REALTY CORP. (023932)","value":"023932","category":"RC"}
Solving the first question above may answer my second question so I will wait to ask that until after.
You can use functions for the request parameters.
var searchDataSource = new kendo.data.DataSource({
transport: {
read: function (options) {
$.ajax({
type: 'POST',
url: Firm.ProfitabilitySearchURL,
contentType: 'application/json; charset=utf-8',
data: {
searchValue: function () {
// better: use a model property instead of this
return $("#TKSearch").data('kendoMaskedTextBox').value();
}
},
success: function (data) {
options.success(data.RESULT);
}
});
}
},
group: { field: 'category' },
serverFiltering: true
});
Notes
This really should be a GET request. Use POST for requests that actually change data on the server and GET for requests that merely retrieve data from the server.
You do not have to JSON.stringify() yourself. jQuery does that transparently.
Specifying dataType is completely superfluous, jQuery will figure this out from the response headers.
Reading the input value via jQuery is not clean. Use the data-bound model property instead.
The callback invocation (options.success())
This sample lacks HTTP error handling, you must add that.
I have a scenario as follows,
Need to put autocomplete functionality on dynamic textbox with onkeyup functionality
My code is as follows, Here i have invoked a function "GetName" on buttonclick where am loadin the dynamic textboxes
function GetName() {
var dataToSend = JSON.stringify({ prefixText: $('#search').val(), Id: $("#SearchType").val()
});
$.ajax({
type: "POST",
data: { jsonData: dataToSend },
url: "GetName",
datatype: "json",
success: function (result) {
$("#ResourceNames").empty();
$("#ResourceNames").append('<table>');
$.each(result, function (i, Name) {
$("#ResourceNames").append('<tr><td ><Label>' + Name.Value + '</label></td><td> <input type="text" id="Supervisor" class = "form-control", onkeyup="GetResource(\'' + Name.Text + '\');"/></td></tr>');
});
},
error: function (xhr, status) {
alert(status);
}
})
$("#ResourceNames").append('</table>');
}
Here onkeyup event of textbox supervisor am calling the below function getresource with an argument
function GetResource(i) {
debugger;
var dataToSend = JSON.stringify({ prefixText: $("#Supervisor").val(), designation: i });
$.ajax({
url: "GetSupervisor",
data: { jsonData: dataToSend },
dataType: 'json',
type: 'POST',
success: function (data) {
$("#Supervisor").autocomplete({source:data});
});
},
error: function (error) {
alert('error; ' + error.text);
}
});
}
am not able to bind autocomplete data to dynamic textbox, can anyone help me out on the same?
You have several issues in your code:
First of all jQuery doesn't concatenates strings into DOM, it creates a DOMElement. So,
$("#ResourceNames").append('<table>'); will append an entire <table> element. Anything you append to #ResourceNames will be added after the table, not inside it.
The HTML you're appending contains id. So there can be multiple elements with same id which is invalid, depending on the response. It's better to use a common classname for those elements instead.
You don't need to manually handle the keyup event. You can specify the url you want to hit as the value of the source option of autocomplete, provided it returns a response suitable for the autocomplete. see this example in docs.
Instead of passing the value via the inline handler, you can store the value as a data-* attribute and access it later.
So your code should be something along:
function GetName() {
var dataToSend = JSON.stringify({ prefixText: $('#search').val(), Id: $("#SearchType").val()});
$.ajax({
type: "POST",
data: { jsonData: dataToSend },
url: "GetName",
datatype: "json",
success: function (result) {
var htmlString ="<table>";
$.each(result, function (i, Name) {
htmlString +="<tr><td ><Label>" + Name.Value + "</label></td><td> <input type='text' class = 'form-control Supervisor' data-name='"+ Name.Text + "'/></td></tr>";
});
},
error: function (xhr, status) {
alert(status);
}
})
$("#ResourceNames").append(htmlString);
$(".Supervisor")..autocomplete({
source: "GetSupervisor" // where GetSupervisor is your data source
});
}
If you want to manually send requests along with data and pass the results into the autocomplete, you can specify an function as the value of source option. (See my another answer for more info). for example:
$(".Supervisor").autocomplete({
source: function(request,response){
/*send the request here.
request.term contains the current value entered in textfield
pass the results you want to display like response(data)*/
}
});
Read the API documentation, play with it for a while and you'll be able to get it working.
html part
<input data-bind="kendoComboBox: { dataTextField: 'FirstName', dataValueField: 'PersonID', data: AllUsers,template: '<span>#= data.FirstName # #= data.LastName # </span>', value: SelectedUserID,
change: UserSelectionChanged}" />
event handler inside model
var self= this;...
self.UserSelectionChanged = function () {
$.ajax({
type: "POST",
url: defaultUri + '/Home/GetUserTasks',
data: JSON.stringify({ PersonID: self.SelectedUserID() }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (o) {
self.SelectedUserTask(null);
self.SelectedUserTask(o);
//RRM: Added this line below so that whenever user dropdown is changed or refresh button is clicked in AssignedTo the first task of that particular user is Selected.
self.selectTask(o[0]);
}
});
};
here the event is being called but the data in self is not there. The event doesn't seems to be bind well with knockout.
how to properly bind the ko event in the kendo combobox event?
Instead of registring to the change event, I'd subscribe to SelectedUserID:
var self= this;
...
self.SelectedUserID.subscribe(function(selectedUserId) {
$.ajax({
type: "POST",
url: defaultUri + '/Home/GetUserTasks',
data: JSON.stringify({ PersonID: selectedUserId }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (o) {
self.SelectedUserTask(null);
self.SelectedUserTask(o);
//RRM: Added this line below so that whenever user dropdown is changed or refresh button is clicked in AssignedTo the first task of that particular user is Selected.
self.selectTask(o[0]);
}
});
});
This way it doesn't matter when or how the SelectedUserID is being changed.
As sroes wrote subscribing to the observable is the best choice here.
In cases where you have to bind to the kendo event then you can do this:
data-bind="... change: UserSelectionChanged(), ...."
Notice the function call parenthesis at the end ^
Now you function has to be like this:
this.UserSelectionChanged = function () {
var self = this;
return function(e) {
$.ajax({
self.blah ...
});
}
}
Now you have created a closure and you can access your view model using self but you also have the original Telerik event args inside e like e.dataItem etc.
So now you are unstoppable, you can do everything!
I have a video thumbnail on my page, with a little icon "Thumbs Down". When you click on that, another thumbnail shows, replacing the other. User can do that as much as they want.
My code is now working only the first time. HTML:
AJAX:
$('.dislike_black').click(function(e) {
e.preventDefault();
alert("test");
var $aTag = $(this);
$.ajax({
url: $aTag.attr('href'),
type: "POST",
data: {
"sort": $aTag.data('sort'),
"page": $aTag.data('page')
},
success: function(response) {
$aTag.parents("li").replaceWith(response);
}
});
});
When I click the icon the first time, its all fine, triggers the alert, the second time thought, no alert, and the browser is loading the href link.
I tried .preventDefault(); on the success and the complete event, but its not working.
Any hint on how to do this?
Your content is dynamically created so, depending on the version of jQuery you are using, you need the jQuery.live() or jQuery.on() method
jQuery.live() since jQuery 1.3 an event handler for all elements which match the current selector, now and in the future.
jQuery.on() since jQuery 1.7 - Attach an event handler function for one or more events to the selected elements.
Sample
jQuery.live()
$('.dislike_black').live("click", function(e) {
e.preventDefault();
alert("test");
var $aTag = $(this);
$.ajax({
url: $aTag.attr('href'),
type: "POST",
data: {
"sort": $aTag.data('sort'),
"page": $aTag.data('page')
},
success: function(response) {
$aTag.parents("li").replaceWith(response);
}
});
});
jQuery.on()
$('.dislike_black').on("click", function(e) {
e.preventDefault();
alert("test");
var $aTag = $(this);
$.ajax({
url: $aTag.attr('href'),
type: "POST",
data: {
"sort": $aTag.data('sort'),
"page": $aTag.data('page')
},
success: function(response) {
$aTag.parents("li").replaceWith(response);
}
});
});
More Information
jQuery.live()
jQuery.on()
Because you are replacing the dom which contains the anchor itself by new html in the ajax success handler. In this case you should use on which will attach event handler to parent or document element whatever you pass as the root element but will trigger the event only on the matching selector which you pass as the second argument. Try this.
$(document).on('click', '.dislike_black', function(e) {
e.preventDefault();
alert("test");
var $aTag = $(this);
$.ajax({
url: $aTag.attr('href'),
type: "POST",
data: {
"sort": $aTag.data('sort'),
"page": $aTag.data('page')
},
success: function(response) {
$aTag.parents("li").replaceWith(response);
}
});
});
.on() reference: http://api.jquery.com/on/ (Ver. 1.7+)
If you are using older version of jQuery you can still achieve this using delegate method whose syntax is same as on but just the first 2 arguments are interchanged.
$(document).delegate('.dislike_black', 'click', function(e) {
//Your code here
});
.delegate() reference: http://api.jquery.com/delegate/
try
$(document).delegate('.dislike_black',"click",function(e) {
Try using event delegation.
// older jquery, use this line:
// $( ".dislike_black" ).live( "click", function ( e ) {
$( document ).on( "click", ".dislike_black", function ( e ) {
e.preventDefault();
alert( "test" );
var $aTag = $( this );
$.ajax( {
url : $aTag.attr( 'href' ),
type : "POST",
data : {
"sort" : $aTag.data( 'sort' ),
"page" : $aTag.data( 'page' )
},
success: function ( response ) {
$aTag.parents( "li" ).replaceWith( response );
}
});
});