Overview:
This is the first post in the series “Getting Started Series on Kendo UI Wrappers for ASP.NET MVC”. In this post we will look at Kendo AutoComplete wrapper. If you are new to Kendo UI Wrappers for ASP.NET MVC, I suggest that you go through “Jumpstarting Development with Kendo UI for ASP.NET MVC” by Abhishek Kant . This post, as the name suggests will give you a jumpstart on Kendo UI Wrappers for ASP.NET MVC.
Lets go ahead and look at the AutoComplete Wrapper in detail.
What is The AutoComplete control?
The AutoComplete control provides suggestions depending on the typed text. It also allows multiple value entries. As the user types, the autocomplete control will suggest items from source that the control is bound to. The user can then select one or many items depending on the configuration. Multiple values will be separated by a delimiter.
Creating ASP.NET MVC Project:
If you have installed the Kendo UI Complete using the installer, you will find project templates to create a new ASP.NET MVC project with Kendo UI Wrappers. This template makes it easy to work with wrappers as it sets up all the right references to the assemblies. If you select File > New Project, select Telerik > Web from the installed template and select “C# Kendo UI for MVC Web Application” from the project template and select Ok.
If you have the extensions but not the installer, then make sure you follow the instructions here to add the assembly’s and correct js/css references.
Instantiating Kendo AutoComplete:
Now that we have created an ASP.NET MVC project, lets see how we can use the Kendo AutoComplete control. For this post, I will be using the Razor syntax and all code will be written in Home/Index view. Now lets instantiate a Kendo AutoComplete control on the page. Here is the code snippet of how that can be done:
@(Html.Kendo().AutoComplete().Name("kautocomplete"))
As you can see we support the Fluent interface so you can chain the calls. All we have done here is to use the Kendo helper and instantiate an AutoComplete. Technically the AutoComplete() is actually a builder which knows how to spit out the Kendo AutoComplete UI js/css on the client side. One more thing that is necessary is to name the control. So we use the Name() method to provide a name to the control. With the above lines placed, we see the following output:
Providing a Place Holder:
Placeholder is nothing but a default text that will be shown on the control when no value is selected by the user. The AutoComplete supports a PlaceHolder() method which takes a text as input. Here is a code snippet of how to use the Placeholder:
1: @(
2: Html.Kendo().AutoComplete()
3: .Name("kautocomplete")
4: .Placeholder("Select contry...")
5: )
The output will be as below’:
Providing Data Source to AutoComplete control:
Now that we have the auto complete on the page lets do some data binding to the control. Currently it does nothing as it does not have a data source to work with. We can provide data in two ways.
-
Provide a data at the time of instantiating the control using the BindTo() method
-
Hooking up a controller action method which will provide data using DataSource() option.
Data binding using BindTo() method:
The signature of BindTo() method is as below:
The input to BindTo() method is an IEnumerable, which means you can just pass any IEnumerable data you may have during the instantiation itself and the control will be bound to that. For instance say we want to bind the auto complete control to list of country names which are held in string array. Here is the code snippet to do that:
1: @(
2: Html.Kendo().AutoComplete()
3: .Name("kautocomplete")
4: .Placeholder("Select contry...")
5: .BindTo(new string[] {"Bulgaria","USA","India","Australia","UK"})
6: )
As you can see I have just bound a simple string array to the auto complete control and this will be the data source now. Here is the output of the above changes:
The autocomplete control filtered the data source based on what the user has typed and presented only those items which matched the input. We will look at the filtering mechanism in a minute.
Data Binding using DataSource() option:
Another way to provide data to autocomplete control is using the DataSource() method. The DataSource method accepts a read only data source provider. We just need to configure which action method on which controller is responsible to provide the data for the control. Autocomplete will automatically issue an AJAX request to the configured action method and retrieve the data, then bind it to autocomplete. Note that the action method should return a JsonResult as autocomplete will make AJAX request to retrieve the data. Here are the code snippets to achieve this:
Controller Action Method:
1: public JsonResult GetCountries()
2: {
3: var countries = new string[] { "Bulgaria", "USA", "India", "Australia", "UK" };
4: return Json(countries, JsonRequestBehavior.AllowGet);
5: }
View:
1: @(
2: Html.Kendo().AutoComplete()
3: .Name("kautocomplete")
4: .Placeholder("Select contry...")
5: .DataSource(source => {
6: source.Read(read =>
7: { read.Action("GetCountries", "Home"); });
8: })
9: )
As you can see we just set the action method name & the controller name on the data source. Here is how the JSON data looks like at runtime. I have used Developer Tools inside IE to look at the payload. Just press F12 on the page, get to Network tab and start capturing the network traffic:
Custom Templates:
AutoComplete also has a flexibility to style the suggestion that is shown by providing your own template. For e.g. in our demo code we have written so far, we have bound the autocomplete to country names. What if we want to show the country flag before the country name when the suggestion is made. Well we can do that by providing an HTML template. We can access the data with a ${data} pattern. Here is the code snippet for providing the custom template:
1: @(
2: Html.Kendo().AutoComplete()
3: .Name("kautocomplete1")
4: .Placeholder("Select contry...")
5: .BindTo(new string[] { "Bulgaria", "USA", "India", "Australia", "UK" })
6: .Template("<span><img src='/Content/Images/${data}.jpg' " +
7: "width='20' height='20' /> ${data}</span>")
8: )
Filtering the results:
By default the autocomplete filters the suggestions based on a logic “Starts With” i.e. it searches for the items which starts with the user typed text. Autocomplete provides a way to control this filtering by means of Filter() method. The Filter method has 2 overloads – one accepts the string “StartsWith” & “Contains” and another accepts a enum of type FilterType. So here is the code snippet to set the filter type to be “Contains”:
1: @(
2: Html.Kendo().AutoComplete()
3: .Name("kautocomplete1")
4: .Placeholder("Select contry...")
5: .BindTo(new string[] { "Bulgaria", "USA", "India", "Australia", "UK" })
6: .Template("<span><img src='/Content/Images/${data}.jpg' " +
7: "width='20' height='20' /> ${data}</span>")
8: .Filter(FilterType.Contains)
9: )
I have the filter logic to be Contains. So here is the output of above code change:
Filtering data on Server:
By default the AutoComplete will do the filtering of items based on user typed text on the client side. This may work fine for small list of data. But if you have very huge list of data items, this pattern may be a hit on performance because everything needs to be downloaded to the client side and then do the filter. If you ask if there is any better way, well answer is yes and the solution is server side filtering. Instead of filtering the data on the client side, autocomplete control provides a way to send the user typed text to server side. The server side code can then filter the data based on the text passed and return only the matching items. Lets look at the code to achieve this:
For the same of the demo, assume we have a EF context created for Northwind database and we want to list the products in an autocomplete control based on user typed text. We will have a GetProducts action method which accepts a single parameter of type string and lets call it as queryText. Here is the controller action method code snippet:
1: public JsonResult GetProducts(string text)
2: {
3: var northwind = new NorthwindDataContext();
4: var products = northwind.Products.Select(product =>
5: new ProductViewModel
6: {
7: ProductID = product.ProductID,
8: ProductName = product.ProductName,
9: UnitPrice = product.UnitPrice ?? 0,
10: UnitsInStock = product.UnitsInStock ?? 0,
11: UnitsOnOrder = product.UnitsOnOrder ?? 0,
12: Discontinued = product.Discontinued
13: });
14: if (!string.IsNullOrEmpty(text))
15: {
16: products = products.Where(p => p.ProductName.Contains(text));
17: }
18: return Json(products, JsonRequestBehavior.AllowGet);
19: }
We first instantiate the EF context and get the products. We then check if any text has been passed and if passed, filter the products based on the text and return only the matching list.
Now we will see how to configure the autocomplete to support this. Here is the code snippet for this change:
1: @(Html.Kendo().AutoComplete()
2: .Name("products")
3: .DataTextField("ProductName")
4: .Filter("contains")
5: .DataSource(source => {
6: source.Read(read =>
7: {
8: read.Action("GetProducts", "Home")
9: .Data("onAdditionalData");
10: })
11: .ServerFiltering(true);
12: })
13: )
14:
15: <script>
16: function onAdditionalData()
17: {
18: return {
19: text: $("#products").val()
20: };
21: }
22: </script>
First we have created autocomplete control with name “products”. Then for the read action we have given the action method name and the controller name. One addition to the read method is the Data() method. This in-fact is a hook to the read action of autocomplete and allows us to stick any additional data we want to pass on to the action. Take a look at the action method GetProducts, it has a parameter by name text. We are passing whatever user types as a parameter to the method and get back a filtered list. That’s all there it is to achieve a server side filtering.
Accessing AutoComplete control on the client side:
All Kendo wrappers have a very rich client side API. Using the client side API’s we can access the kendo control on the client side and access a rich set of properties, methods and events. Kendo wrappers are built on the latest and greatest HTML5 standards, so the client side code generated makes use of the new “data-“ (data dash) attributes. We can use the jquery data() method and retrieve them. Here is the code to access a autocomplete control on page load:
1: var autocomplete = $("#kautocomplete").data("kendoAutoComplete"),
Here “kautocomplete” is the id of the control and we use the jquery data() method to retrieve the kendo control by passing the string “kendoAutoComplete”. This is pretty much a pattern we use to get access to any kendo wrapper from JavaScript.
This comes in handy for instance, when we want to refresh the auto complete on page load. As you saw in the example of data source binding, an AJAX request is issued to get the items the first time a user types in the textbox. What if you want to load the items on page load and keep the autocomplete ready for filtering. This can be done with the following code snippet:
1: var kac = $("#kautocomplete").data("kendoAutoComplete");
2: kac.refresh();
You can find the complete list of client side API supported by Kendo AutoComplete widget here.
Summary:
In the first of the many posts to come on Kendo Wrappers for ASP.NET MVC, in this post, we looked at AutoComplete control. We looked at the basics of the using the control and various features like Data Binding, Filtering, Custom Templates and accessing the control from the client side. Hope this excites you to take a dig at the Kendo Wrappers for ASP.NET MVC. Download the free 30 day trial and kick start your kendo adventure.
Till next time – Happy Coding.
Pingback: Getting Started Series on Kendo UI Wrappers for ASP.NET MVC « Telerik Helper
I have put this together exactly as you have shown, using the “Filtering on server” section. I am using this as a partial view on another view, but otherwise it’s the same (different controller, of course). The issue I am having is that the search term passed into the controller action is always null. When I force a value into the variable (overriding the action method constructor), it works as expected. Am I missing something? Thanks
Is there a working sample of this?
Is it possible to give MVC Area definition in the Ajax binding of AutoCompleteFor ?
Yes you can …
Pingback: Lindermann's Blog | Kendo AutoComplete Wrapper for ASP.NET MVC
Pingback: Top 5 Blog Posts of 2014 | telerik helper