AutoComplete Textbox in AngularJS with Dynamic Data using Web API C# and Vb.Net

← PrevNext →

I have previously shared some very useful articles on AutoComplete textbox using various methods in jQuery, HTML5 etc. You know it’s a very important feature that you’ll often need while working with forms and textboxes. It automatically provides a list of words when you type a letter in a textbox. Here in this post, I’ll share a simple example on how to implement AutoComplete feature in AngularJS with Dynamic data from SQL Server Database using Web API.

AutoComplete Textbox in AngularJS using Dynamic Data with Web API

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.

See this demo

Library angucomlete-alt

You will first need to download a library to implement AutoComplete feature in you AngularJS application.

Download angucomlete-alt

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.

The Model Books.cs (C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace BooksApp.Models
{
    public class Books
    {
        public string BookName { get; set; }
    }
}
The Model Books.vb (Vb.Net)
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
The Controller “BooksController.cs” (C#)
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();
                }
            }
        }
    }
}
The Controller “BooksController.vb” (Vb.Net)
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
WebApiConfig File (C#)
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}/"
            );
        }
    }
}
WebApiConfig File (Vb.Net)
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.

The Markup

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>
The Body
<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>
See this demo

← PreviousNext →