An application can provide dynamic data using various data source such as XML, SQL Server etc. Here however, I’ll use SQL Server as my data source for the AutoComplete feature. I am also using a Web API controller to request the data from the database.
Note: I have written the Web API in C# and Vb.Net.
Library angucomlete-alt
You will first need to download a library to implement AutoComplete feature in you AngularJS application.
The download provides a Zip file. Inside you will find a folder named example. Further inside, you will see a folder named css, with two files named angucomplete-alt.css and structure.css.
You’ll have include these files in your AngularJS app (default.htm file), inside the <head> tag.
<link href="http://localhost:12345/content/angucomplete-alt.css" rel="stylesheet" /> <link href="http://localhost:12345/content/structure.css" rel="stylesheet" />
See the markup section below for more details.
Create an SQL Server Table
The Web API will extract data from an SQL Server table called the Books. Yes, I am fond of books and I already have a books table created for examples such as this. Here you can find the table.
Now, let’s build our Web API in Asp.Net, the controller and model.
If you are new to Web API, then I would suggest you click the below link to learn how to build an Asp.Net Web API from the start.
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace BooksApp.Models { public class Books { public string BookName { get; set; } } }
Imports System.Web Namespace BooksApp.Models Public Class Books Public Property BookName() As String Get Return m_BookName End Get Set(value As String) m_BookName = value End Set End Property Private m_BookName As String End Class End Namespace
using System; using System.Collections.Generic; using System.Net.http; using System.Web.http; using System.Data.SqlClient; using BooksApp.Models; namespace BooksApp { public class BooksController : ApiController { string sConnString = "Data Source=DEMO;Persist Security Info=False;" + "Initial Catalog=DNA_Classified;User Id=sa;Password=demo;Connect Timeout=30;"; List<Books> myBooks = new List<Books>(); public IEnumerable<Books> Get() { GetData(); return myBooks; } private void GetData() { using (SqlConnection con = new SqlConnection(sConnString)) { string sQuery = null; sQuery = "SELECT *FROM dbo.Books"; using (SqlCommand cmd = new SqlCommand(sQuery)) { cmd.Connection = con; con.Open(); SqlDataReader reader = cmd.ExecuteReader(); // POPULATE THE LIST WITH DATA. while (reader.Read()) { myBooks.Add(new Books { BookName = reader["BookName"].ToString() }); } con.Close(); } } } } }
Option Explicit On Imports System.Net.http Imports System.Web.http Imports System.Data.SqlClient Imports BooksApp.BooksApp.Models Namespace BooksApp Public Class BooksController Inherits ApiController Const sConnString As String = "Data Source=DEMO;Persist Security Info=False;" & _ "Initial Catalog=DNA_Classified;User Id=sa;Password=demo;Connect Timeout=30;" Dim myBooks As New List(Of Books)() Public Function [Get]() As IEnumerable(Of Books) GetData() Return myBooks End Function Private Sub GetData() Using con As SqlConnection = New SqlConnection(sConnString) Dim sQuery As String sQuery = "SELECT *FROM dbo.Books" Using cmd As SqlCommand = New SqlCommand(sQuery) With cmd .Connection = con con.Open() Dim reader As SqlDataReader = .ExecuteReader() ' POPULATE THE LIST WITH DATA. While reader.Read() myBooks.Add(New Books() With { _ .BookName = reader("BookName").ToString() _ }) End While con.Close() End With End Using End Using End Sub End Class End Namespace
using System; using System.Collections.Generic; using System.Linq; using System.Web.http; namespace BooksApp { public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/" ); } } }
Imports System Imports System.Collections.Generic Imports System.Linq Imports System.Web.http Public Class WebApiConfig Public Shared Sub Register(ByVal config As HttpConfiguration) config.Routes.MapHttpRoute( _ name:="DefaultApi", _ routeTemplate:="api/{controller}/" _ ) End Sub End Class
Well, if you are ready with you Web API, you can design you AngularJS app. Simply add a default.htm file in you .Net application.
As I have mentioned in the beginning, you have to include the AutoComplete library (.js file) and two CSS files in your AngularJS app.
If you have created the Web API using Asp.Net, then you will see a folder named Content in your root directory. Copy the css files inside the Content folder.
Now to include the .js file I am using a CDN in my app. Here’s the link for latest version of angucomplete-alt.
The <head> section will look like this.
<!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angucomplete-alt/2.5.0/angucomplete-alt.min.js"></script> <link href="http://localhost:12345/content/angucomplete-alt.css" rel="stylesheet" /> <link href="http://localhost:12345/content/structure.css" rel="stylesheet" /> </head>
However, I wish to customize the AutoComplete feature in my app. Therefore, instead of adding the .css files in the <head>, I have extracted few attributes from the files and added it inside the <style> tag (Internal Style).
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/angucomplete-alt/2.5.0/angucomplete-alt.min.js"></script> <style> .angucomplete-holder { position:relative; font:15px Verdana; } .angucomplete-dropdown { font:inherit; border-color:#ececec; border-width:1px; border-style:solid; border-radius:2px; width:300px; padding:6px; cursor:pointer; position:absolute; z-index:9999; top:36px; left:0px; margin-top:-6px; background-color:#fff; overflow-y:auto; max-height:150px; } .angucomplete-searching { font:inherit; font-size:85%; color:#999; letter-spacing:1px; } .angucomplete-row { padding:5px; margin-bottom:4px; color:#000; clear:both; } .angucomplete-selected-row { background-color:#428bca; color:#fff; } .form-control { outline:0; border-color:#ECECEC; border-style:solid; border-width:1px; width:300px; background-color:#fff; padding:6px; border-radius:2px; margin-bottom:5px; font:inherit; font-size:90%; } .highlight { font-weight:bold; color:#dc143c; } </style>
<body> <div ng-app="myApp" ng-controller="myController"> <p angucomplete-alt id="books" class="angucomplete-holder" placeholder="Search your Book" maxlength="50" pause="100" selected-object="selectedBook" local-data="myBooks" search-fields="bookName" title-field="bookName" minlength="1" input-class="form-control" match-class="highlight"> </p> <p ng-show="selectedBook"> <b>You selected</b>: {{selectedBook.originalObject.bookName}} </p> </div> </body>
I am using very limited features here, as per my requirement. However, this awesome widget provides many other interesting features.
Look at the local-data attribute with a value myBooks. I am pushing JSON data to it through my Controller using $scope. See the script below.
The attribute search-fields has the name of the JSON object bookName. The API returns the name of books in the database.
The match-class attribute will highlight the matching characters when you type letters (characters) in the textbox. You can further customize it in the CSS file. See the demo below.
The AngularJS Controller with $http
Finally, here’s my controller to request the data from the Web API controller. I have added the angucomlete-alt module to my AngularJS controller.
<script> var myApp = angular.module('myApp', ['angucomplete-alt']); myApp.controller('myController', function ($scope, $http) { var arr = new Array(); $http.get("/api/books/").success(function (data) { angular.forEach(data, function (item) { arr.push({ bookName: item.BookName }); }); $scope.myBooks = arr; }).error(function (XMLHttpRequest, textStatus, errorThrown) { alert(textStatus); }); }); </script> </html>