Cascading Combobox with default values on telerik mvc - asp.net-mvc

I have a search page and want to add some filters to it, my setup is quite simple, I have a CombobBox for Countries and a ComboBox for States.
I want to show ALL the states if no country is selected(actually, the first item of the countries combobox is "All") here is my code:
#(Html.Telerik().ComboBoxFor(m => m.Country)
.Name("cbxCountry")
.BindTo(this.Model.CountryList)
.SelectedIndex(0).CascadeTo("cbxStates"))
#(Html.Telerik().ComboBoxFor(m=>m.State)
.Name("cbxStates")
.DataBinding(binding => binding.Ajax()
.Select("AjaxLoadStates","States")))
Note that even if the .SelectedIndex is set to 1, 3, 1231231 the second combobox keeps disabled until I select a value. Is there any way to make this work?

You can do this with the client API in javascript:
<script type="text/javascript">
function SelectFirstCountry() {
var cbxCountry = $("#cbxCountry").data('tComboBox')
var cbxStates = $("#cbxStates").data('tComboBox')
cbxCountry.select(1);
cbxStates.enable();
}
$(document).ready(function () {
#{
Html.Telerik().ScriptRegistrar().OnDocumentReady("SelectFirstCountry()");
}
});
</script>

Related

How to keep model up to date with dynamic datasource?

In the case that I am fetching Country and State data from an API, I can't seem to keep the link to the model after updating a kendo combobox's data source.
Let's say that there is a form that will be used internationally. So we want to provide a Country Combobox and a State Combobox and then filter the state by the selected country. If the user selects a country, then the state combobox updates. This is great! However, when I go to submit, the stateid field in the model is null.
I've tried manually changing the datasource, and can't really find any more information on this kind of issue. If anyone can point me in the right direction, that would be greatly appreciated.
Data model:
class ExampleModel {
[display(name='StateId')]
int? stateId;
[display(name='CountryId')]
int? countryId
}
razor:
<div id='country-wrapper'>
#(Html.Kendo().ComboBoxFor(m => m.CountryId)
.Filter("contains")
.Placeholder("-- Select Country --")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new SelectList(stateList, "CountryId", "CountryName", 1))
.Suggest(true)
.HtmlAttributes(new { #id = "CountryId", onchange = " CountryChangeEvent(this); ComboChangeEvent(this);"
}));
</div>
<div id='state-wrapper'>
#(Html.Kendo().ComboBoxFor(m => m.StateId)
.Filter("contains")
.Placeholder("-- Select State --")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new SelectList(stateList, "StateId", "StateName"))
.Suggest(true)
.HtmlAttributes(new { #id = "StateId", onchange = "ComboChangeEvent(this)"
}));
</div>
js:
function CountryChangeEvent(elem) {
var chosenId = $("#CountryId").data('kendoComboBox').value();
if (!chosenId) return;
$("#ProfileStateId").kendoComboBox({
dataTextField: "Text",
dataValueField: "Value",
dataSource: {
transport: {
read: {
// call this method in the controller and reset datasource
cache: false,
serverFiltering: true,
async: false,
dataType: "json",
url: '#Url.Action("GetStatesByCountryJson", "Home")?countryId=' + chosenId,
}
}
},
filter: "contains",
suggest: true
});
var combobox = $("#StateId").data('kendoComboBox');
combobox.select(function (dataItem) {
// clear the statecombobox
return dataItem.Value === '';
});
}
Expected
I would expect that the state list would change when the CountryChangeEvent function is called. Also, when you submit the form, the StateId value would be stored in the model.
Actual
It does in fact change the state combobox visually. You can see all of the states and filter. However, when you submit and debug, you can see that the StateId in the model is null.
Current workaround/hack
I have found that if I download all states(for all countries) in the beginning, then it works as intended.
I found another workaround/hack that works much better than downloading all states on load. I changed the control from a combo box to a drop down list and voila, it works now.
No idea why this didn't work, but I'll close it since my problem was fixed, and a combo box is really over kill for this kind of problem anyway.
If you come across this problem hoping for a solution look into cascading dropdownlist
Courtesy of CarstenFranke
Should work better for you.

JQuery UI Autocomplete widget not working on a bootstrap modal

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.

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.

how to catch PageSizeChanged event of telerik MVC Grid (NOT KENDO GRID)

I am working on asp.net MVC 4 application in which i am using telerik MVC Grid (NOT KENDO GRID).
http://www.telerik.com/help/aspnet-mvc/telerik-ui-components-grid-client-api-and-events.html
in my page (cshtml) i am having the grid using the common partial page.
in the page, i am also having other input elements ( which acts as filter criteria for grid data).User selects the values from input elements and click on submit button and data in grid is filled accordingly (using post requst in MVC code).
I am using paging in grid and user may select the page size.
Grid set up
Html.Telerik().Grid(Model)
.Name("Employees")
.Columns(cols =>
{
cols.Bound(e => e.FirstName).Title("First Name");
cols.Bound(e => e.LastName).Title("Last Name");
cols.Bound(e => e.SSN).Title("SSN");
cols.Bound(e => e.HireDate).Format("{0:MM/dd/yyyy}").Title("Hire Date");
cols.Bound(e => e.GroupName).Title("Department GROUP");
})
.Groupable()
.Sortable(x => x.OrderBy(z=>z.GetType()))
.Pageable(p => p.PageSize(5).Style(GridPagerStyles.PageSizeDropDown | GridPagerStyles.NextPreviousAndNumeric).PageTo((Model.Any()&&!string.IsNullOrWhiteSpace(Model.First().PageNumber)?Convert.ToInt32(Model.First().PageNumber):1)))
.Filterable()
.Render();
the POST method in employee controller returns the filtered data by accepting the model values and querying the database.
now when changes the page size of the grid,request is sent to GET method of the controller instead of post.
How to catch PageSizeChanged like event of grid in JavaScript, so that i can manually post the form wherever user change page size?
EDIT : I have written following code to get click event whenever user clicks on number in page size dropdown
$(document).on('click', 'ul.t-reset > li.t-item', function (e) {
//how to avoid default functionality of server call?
//tried following
//event.unbind();
//event.preventDefault();
//alert("Was preventDefault() called: " + event.isDefaultPrevented());
//event.stopImmediatePropagation()
//return false;
});
MVC Grids just get turned into Kendo Grid javascript, so all the API methods/events and so on can be used with the MVC Grid.
Check out the kendo grid page change event and just use that.
http://docs.telerik.com/kendo-ui/api/javascript/ui/pager#events-change
var grid = $("#Employees").data('kendoGrid');
Now you have the grid, you can do whatever you wish to it. Subscribe to the page event change like the example from Kendo API documentation;
<div id="pager"></div>
<script>
function pager_change() {
console.log("pager change event");
}
var dataSource = new kendo.data.DataSource({
data: [
{ productName: "Tea", category: "Beverages" },
{ productName: "Coffee", category: "Beverages" },
{ productName: "Ham", category: "Food" },
{ productName: "Bread", category: "Food" }
],
pageSize: 2
});
dataSource.read();
var pager = $("#pager").kendoPager({
dataSource: dataSource
}).data("kendoPager");
pager.bind("change", pager_change);
</script>
I like to set up the grid with MVC and if I need to get into its workings and do a lot of client side magic I'll just grab it as a Kendo grid.

Having trouble with jQueryUI accordion and Knockoutjs

I've been able to replicate the problem here: http://jsfiddle.net/NE6dm/
I have the following HTML which I'm using in an app:
<div data-bind="foreach: items, jqAccordion: { active: false, collapsible: true }">
<h3>
</h3>
<div>
hello
</div>
</div>
<button title="Click to return to the complaints list." data-bind="click: addItem">Add Item</button>
The idea is to display an accordion for a bunch of items that will dynamically be added/removed via a Knockout observable array.
Here's some JavaScript code which I use:
// Tab.
var tab = function (questionSet) {
this.id = questionSet.code;
this.title = questionSet.description;
this.questionSet = questionSet;
};
Custom Knockout binding handler:
ko.bindingHandlers.jqAccordion = {
init: function (element, valueAccessor) {
var options = valueAccessor();
$(element).accordion(options);
$(element).bind("valueChanged", function () {
ko.bindingHandlers.jqAccordion.update(element, valueAccessor);
});
},
update: function (element, valueAccessor) {
var options = valueAccessor();
$(element).accordion('destroy').accordion(options);
}
};
var NonSequentialViewModel = function () {
var items = ko.observableArray();
items.push(new tab({ id: 23, description : 'Added Inline' }));
var addItem = function() {
items.push(new tab({ id: 5, description: 'Added by a click' }));
};
return {
addItem: addItem,
items: items
}
}
var nonsequentialViewModel = new NonSequentialViewModel();
ko.applyBindings(nonsequentialViewModel);
Now the problem is this - when I view the HTML page, the item 'Added Inline' appears fine, in that I can collapse and expand it. However, when I click the button 'Add Item', a new item is added to he accordion, but it has not styling at all. For example:
In the above image, the first item is styled correctly, however the remaining items have none of the jQuery UI styling applied. Basically, any item which is added dynamically does not have any accordion styling applied.
I have seen this question
knockout.js and jQueryUI to create an accordion menu
and I've tried using the jsFiddle included in the question, but I cannot see why my code doesn't have the same result.
I'm hoping someone else has experienced this before and can help.
EDIT:
I've looked into this further and see that the problem is this - when I add a new item to the oservable array, the custom handler's update method is not executed. Thus the redrawing of the accordion never happens.
I can't see why the update should not be called. This is realyl doing my head in! :)
EDIT:
I've been able to replicate the problem here: http://jsfiddle.net/NE6dm/
Your NonSequentialViewModel constructor doesn't return items array. Update return statement to this:
return {
items: items,
addItem: addItem
}
Here is working fiddle: http://jsfiddle.net/vyshniakov/MfegM/323/
Old question, but I believe I was having the same problem.
I may need to submit a bug to knockout.js. I just spend several hours trying to figure out similar problems.
In short... if I load your jsfiddle and change the version of knockout to 2.1.0, it appears to work fine.
this:
<script type="text/javascript" src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.2.0.debug.js"></script>
to this:
<script type="text/javascript" src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.debug.js"></script>
(The only difference being the version 2.2.0 --> 2.1.0)
Further... I ended up settling on several versions:
jquery: 1.9.1
jquery-ui (combined): 1.9.2
knockoutjs: 2.1.0

Resources