JQuery UI Autocomplete widget not working on a bootstrap modal - asp.net-mvc

I have a bootstrap modal dialog on which I have a textbox that I want to leverage the functionality of jQuery UI Autocomplete widget. However the autocomplete widget isn't being fired at all. I know this as I placed a breakpoint on the action on my controller that should return the Json to be rendered by the autocomplete textbox. The action is never hit
Out of curiosity that I was doing something wrong, I copy pasted the textbox onto a View and to my dismay, the breakpoint on my action in the controller is hit. I have narrowed this down to the fact that may be the textbox is never wired to use the autocomplete feature once the DOM has loaded.
Here is the textbox on my modal
<input type="text" name="someName" id="autocomplete" data-autocomplete-url="#Url.Action("Autocomplete", "warehouses")" />
Here is the action method that returns the Json
public ActionResult Autocomplete(string term)
{
string[] names = { "Auma", "Dennis", "Derrick", "Dylan", "Mary", "Martha", "Marie", "Milly", "Abel", "Maria", "Bergkamp", "Arsene", "Alex", "Mwaura", "Achieng" };
var filtered = names.Where(a => a.IndexOf(term, StringComparison.OrdinalIgnoreCase) >= 0);
return Json(filtered, JsonRequestBehavior.AllowGet);
}
And here is how I wire up the textbox to use the autocomplete widget
$(document).ready(function () {
$('#autocomplete').autocomplete({
source: $(this).data('autocomplete-url'),
data: {term: $(this).val() }
});
});
I have seen similar questions asked but none of them was due to the action not being hit.

As per the documentation for Bootstrap 3, they expose a set of events that you can hook into with most of their JS features.
In this case the events are:
show, shown, hide, hidden and loaded
The following code will initialize your autocomplete input field after the modal has been shown. (replace myModal with the id of the modal you are going to show)
$(document).ready(function () {
$('#myModal').on('shown.bs.modal', function (e) {
$("#autocomplete').autocomplete('destroy'); //remove autocompete to reattach
$('#autocomplete').autocomplete({
source: $(this).data('autocomplete-url'),
data: {term: $(this).val() }
});
});
});
If you are fetching a partial that contains the input field and appending it to the modal during the toggle, it will be better to do this initialization in the callback from that ajax request.

Related

ASP.NET: How to get from Dropdownlist to Autocomplete

I have a dropdownlist and want to turn it into autocomplete using jquery.
The dropdown looks like this and works:
#Html.DropDownListFor(m => m.CategoryID, new SelectList(Model.Categories, "ID", "Name", Model.CategoryID), "Categories", new { #class = "form-control" })
I also added an autocomplete field using jquery that works. But so far I can only populate it with dummy data:
$(function () {
var availableTags = [
"ActionScript",
"AppleScript",
"Asp"
];
$("#tags").autocomplete({
source: availableTags
});
});
How can I populate my dropdown field with the data that is available in the dropdown?
Thank you in advance!
You need to set the source as an action method which returns data you want to show as autocomplete option in JSON format.
$(function(){
$("#tags" ).autocomplete({
source: "#Url.Action("SearchCategories","Home")",
minLength: 1,
select: function (event, ui) {
//If you want to do something on the select event, you may do it here
//$("#tags").html(ui.item.label);
}
});
})
Make sure you have an action method called SearchCategories in your HomeController which returns the data you want.
public ActionResult SearchCategories(string term)
{
var db= new MyDbContext();
var results = db.Categories.Where(s => s.Name.StartsWith(term))
.Select(x=>new { id =x.Id,
label =x.Name }).ToList();
return Json(results,JsonRequestBehavior.AllowGet);
}
This should enable the autocomplete on an input with id tags,assuming you have jQuery ui library(and it's dependencies) loaded properly in your page and you do not have any other script errors in your page. I have used Url.Action helper method to generate the correct relative url to the action method. It will work fine if your js code is inside a razor view. But if your code is inside an external js file, you should follow the approach described in this post.

JQuery-ui Tabs - reload page with completely new content not working

I'm loading in a report and displaying it with jquery-ui in tab format. The report is returned by an ajax call in json, and a function is formatting it into HTML. Example code below:
<div id="reportdiv">
</div>
<script>
function displayreport(objectid)
{
$( "#reportdiv" ).hide();
$( "#reportdiv" ).html("");
$.ajax({
type: "GET",
headers: { 'authtoken': getToken() },
url:'/reportservice/v1/report/'+objectid.id,
success: function(data){
if(data == null)
{
alert("That report does not exist.");
}
else
{
var retHTML = dataToTabHTML(data.config);
$("#reportdiv").html(retHTML).fadeIn(500);
$(function() {
tabs = $( "#reportdiv" ).tabs();
tabs.find( ".ui-tabs-nav" ).sortable({
axis: "x",
stop: function() {
tabs.tabs( "refresh" );
}
});
});
}
}
});
}
</script>
This works fine the first time displayreport is called. However, if the user enters another value and runs displayreport again, the "tabs" format is completely lost (the tabs are displayed as links above my sections, and clicking on a link takes you to that section further down the page).
I figured completely re-setting the reportdiv html at the beginning of the function would bring me back to original state and allow it to work normally every time. Any suggestions?
After more testing, found that destroy was the way to go. If I've set up tabs already, run the destroy, otherwise, skip the destroy (http://jsfiddle.net/scmxyras/1/) :
if(tabs!=undefined)$( "#reportdiv" ).tabs("destroy");

jQuery Ajax Form Submit Fails

I am developing an MVC4 mobile app that uses several forms which are loaded into a section on the layout via ajax. I've got jQuery mobile set with Ajax turned off so I can manage the Ajax myself. Most of the forms work fine, the load and submit via ajax as they should. However, so far there is one form that refuses to fire the form submit and submit the form via ajax like the rest. First, the form is loaded when a user clicks to add a contact and this works fine:
// Handle the add contact button click
$('#btnAddNewContact').on('click', function (e) {
e.preventDefault();
// Make sure a location was selected first.
var locationID = $('#cboLocation').val();
if (locationID.length === 0) {
//$('#alertTitle').text('REQUIRED');
$('#alertMsg').html("<p>A Contact must be associated with a Location.</p><p>Please select or add a Location first.</p>");
$('#alertDialogDisplay').click();
} else {
SaveOpportunityFormState();
$.cookie('cmdLocationId', locationID, { path: '/' });
$.mobile.loading('show');
$.ajax({
url: '/Contact/Add',
type: 'GET',
cache: false,
success: function (response, status, XMLHttpRequest) {
$('section.ui-content-Override').html(response);
// Refresh the page to apply jQuery Mobile styles.
$('section.ui-content-Override').trigger('create');
// Force client side validation.
$.validator.unobtrusive.parse($('section.ui-content-Override'));
},
complete: function () {
$.cookie('cmdPreviousPage', '/Opportunity/Add', { path: '/' });
AddContactLoad();
ShowSearchHeader(false);
$.mobile.loading('hide');
},
error: function (xhr, status, error) {
// TODO - See if we need to handle errors here.
}
});
}
return false;
});
Notice that after successfully loading the form the AddContactLoad() function is fired. This works fine and here is that code:
function AddContactLoad() {
$('#contactVM_Phone').mask('(999) 999-9999? x99999');
$('#frmAddContact').on('submit', function (e) {
e.preventDefault();
if ($(this).valid()) {
$.mobile.loading('show');
$.ajax({
url: '/Contact/Add',
type: 'POST',
cache: false,
data: $(this).serialize(),
success: function (response, status, XMLHttpRequest) {
if (!response) { // Success
ReturnToAddOpportunity();
} else { // Invalid Form
$('section.ui-content-Override').html(response);
// Force jQuery Mobile to apply styles.
$('section.ui-content-Override').trigger('create');
// Force client side validation.
$.validator.unobtrusive.parse($('section.ui-content-Override'));
AddContactLoad();
$.mobile.loading('hide');
}
},
complete: function () {
},
error: function (xhr, status, error) {
// TODO - See if we need to handle errors here.
}
});
}
return false;
});
$('#btnCancel').on('click', function (e) {
e.preventDefault();
// See where add contact was called from.
var previousPage = $.cookie('cmdPreviousPage');
if (previousPage.indexOf("Detail") >= 0) {
ReturnToOpportunityDetails();
} else {
ReturnToAddOpportunity();
}
return false;
});
}
If I click the cancel button, that code is fired so I know this is working too. Here is my form code:
#using (Html.BeginForm("Add", "Contact", FormMethod.Post, new { #id = "frmAddContact" }))
{
#Html.ValidationSummary(true)
#Html.AntiForgeryToken()
-- Form Fields Here --
<div class="savecancel" >
<input type="submit" value="Save" data-mini="true", data-theme="b", data-inline="true" />
Cancel
</div>
}
As you can see the form is named frmAddContact and that is what the AddContactLoad() function is attaching the submit event to. To save my sole I cannot figure out why the form does not submit via the ajax post like every other form in the app. Am I missing some kind of initialization, I just don't know. If anyone can please help I'd really appreciate it!!
As it turns out, I had created a custom unobtrusive Ajax validator for a phone number then copied and pasted it to do the same with a zip code. Unfortunately in the process I forgot to rename a variable and thus an error was occurring in the validation script which caused the problem. In the mean time, if you're reading this, you might take a note of the code here and how to inject HTML into a page via Ajax and jQuery mobile. I've never found this in a book or on the web and it contains some very useful methodology and syntax. On the form submit the reason I'm checking for the empty response is I just return null from the controller to validate the form was valid and the save worked in which case I send them to a different HTML injection i.e. that page they originally came from. If null is not returned I inject that page with the HTML containing the original form and error markup so the user can make corrections then resubmit. I'm also calling a form load method that attaches handlers to the HTML once it's injected into the main page. Hope this helps somebody!

How to create a modal JQuery UI dialog from a Html page fragment fetched by $.get()

with the below code, I'm able to add a page fragment to an other page. The page contains a form to be posted to a certain action method.
$("#ul-menu a").click(function () {
$.get($(this).attr("href"), function (response) {
$("#dialog-div div").replaceWith($(response));
});
return false;
})
Instead of having the form anywhere in the page, I'd like to get it as a modal JQueryUI dialog.
How can I do that.
Thanks for helping.
This will work for you. Also, I've added a better method of preventing the original click. Instead of returning false, which kills all bubbling, you should use event.preventDefault();
$("#ul-menu a").click(function (event) {
event.preventDefault();
$.get($(this).attr("href"), function (response) {
$(response).dialog({ modal : true });
});
})
You don't even need to insert the response into the page.
You can just do this:
var myDialog = $(response).dialog();
EDIT
Not the above snippet won't create a modal dialog, I assumed you know you need to pass in { modal: true } as part of your configuration.

How can I close the jquery ui dialog from inside the dialog code?

I use several jquery ui dialogs in my application to collect input from users and for CRUD operations. When in a page I need a dialog I do the following steps:
First I define the minimum markup and code necessary to initialize the dialog like this
<div id="dialogPanel" style="display:none" title=""></div>
and, when the DOM is ready,
$("#dialogPanel").dialog({
autoOpen: false, hide: 'slide', show: 'bounce', resizable: false,
position: 'center', stack: true, height: 'auto', width: 'auto',
modal: true, overlay: { opacity: 0.5, background: "white" }
});
Then I load content in the dialog when I need it using ajax calls, like this
<button id="addCustomer">Add Customer</button>
and this
$("#addCustomer").button().click(function(event) {
event.preventDefault();
loadDialog("/Customer/Create", "", "Add New Customer");
});
function loadDialog(action, id, title) {
$("#dialogPanel").dialog("option", "title", title);
if (id != "")
action = action + "/" + id;
$.ajax({
type: "get",
dataType: "html",
url: action,
data: {},
success: function(response) {
$("#dialogPanel").html('').html(response).dialog('open');
}
});
}
The ajax call returns a strong typed view that will show inside the dialog and even resize it dinamically. The strong typed view has some buttons that, in turns, does other ajax calls (for example to the controller action that validate and persist on the database). These calls usually returns back HTML code that will be added to the dialog DIV.
Now my question is: How do I close the dialog? I can do it by clicking the "X" button on top right corner of the dialog or by pressing the ESC key but I would like to do it as a consequence of the click to the button that is inside the strong typed view .
However I do not wish to use this kind of code
$("#dialogPanel").dialog('close');
inside a strong typed view that does not defines the #dialogPanel DIV in itself.
What could be a good solution?
Create a closeDialog function in the main form, and call that function from within the dialog. Then any other page that hosts the dialog also needs to define a "closeDialog" function.
Also, you could pass a delegate pointing to the closeDialog function to separate things further.

Resources