My Scenario: My MVC controller is returning JSON data which is array of string
I tried all the possible solutions like twitter bootstrap typeahed for angular but nothing
Finally I used Angular Material for the autocomplete and it works like a charm. Here are the steps to create autocomplete in Angularjs and MVC4
Step 1:
Angular material has a dependency on
angular-animate.js
angular-aria.js
angular-messages.js
register these js files in your bundle config:
bundles.Add(new ScriptBundle("~/bundles/angularanimatejs").Include("~/Scripts/angular-animate.js"));
bundles.Add(new ScriptBundle("~/bundles/angularariajs").Include("~/Scripts/angular-aria.js"));
bundles.Add(new ScriptBundle("~/bundles/angularmessagesjs").Include("~/Scripts/angular-messages.js"));
Register two css files as well: bundles.Add(new StyleBundle("~/Content/angularmaterialcss").Include("~/Content/angular-material.css")); bundles.Add(new StyleBundle("~/Content/angularmateriallayoutcss").Include("~/Content/angular-material-layout.css"));
Now include these files in shared or your page:
@Styles.Render("~/Content/angularmaterialcss")
@Styles.Render("~/Content/angularmateriallayoutcss")
@Scripts.Render("~/bundles/cdnangularjs")
@Scripts.Render("~/bundles/cdnangularresourcejs")
@Scripts.Render("~/bundles/angularanimatejs")
@Scripts.Render("~/bundles/angularariajs")
@Scripts.Render("~/bundles/angularmessagesjs")
@Scripts.Render("~/bundles/angularmaterialjs")
@Scripts.Render("~/bundles/appjs")
Now in your cshtml page add html code:
<div class="autocompletedemoBasicUsage" ng-controller="DemoCtrl as ctrl" layout="column" ng-cloak="">
<md-content class="md-padding">
<form ng-submit="$event.preventDefault()">
<p>Use <code>md-autocomplete</code> to search for matches from local or remote data sources.</p>
<md-autocomplete ng-disabled="ctrl.isDisabled" md-no-cache="ctrl.noCache" md-selected-item="ctrl.selectedItem" md-search-text-change="ctrl.searchTextChange(ctrl.searchText)" md-search-text="ctrl.searchText" md-selected-item-change="ctrl.selectedItemChange(item)" md-items="item in ctrl.querySearch(ctrl.searchText)" md-item-text="item.display" md-min-length="0" placeholder="What is your favorite US state?">
<md-item-template>
<span md-highlight-text="ctrl.searchText" md-highlight-flags="^i">{{item.display}}</span>
</md-item-template>
<md-not-found>
No states matching "{{ctrl.searchText}}" were found.
<a ng-click="ctrl.newState(ctrl.searchText)">Create a new one!</a>
</md-not-found>
</md-autocomplete>
<br>
<md-checkbox ng-model="ctrl.simulateQuery">Simulate query for results?</md-checkbox>
<md-checkbox ng-model="ctrl.noCache">Disable caching of queries?</md-checkbox>
<md-checkbox ng-model="ctrl.isDisabled">Disable the input?</md-checkbox>
<p>By default, <code>md-autocomplete</code> will cache results when performing a query. After the initial call is performed, it will use the cached results to eliminate unnecessary server requests or lookup logic. This can be disabled above.</p>
</form>
</md-content>
write below code into your app.js file:
(function ()
{
'use strict';
angular
.module('StockMarketApp', ['ngMaterial', 'ngMessages'])
.controller('DemoCtrl', DemoCtrl);
function DemoCtrl($timeout, $q, $log)
{
var self = this;
self.simulateQuery = false;
self.isDisabled = false;
// list of `state` value/display objects
self.states = loadAll();
self.querySearch = querySearch;
self.selectedItemChange = selectedItemChange;
self.searchTextChange = searchTextChange;
self.newState = newState;
function querySearch(query)
{
var results = query ? self.states.filter(createFilterFor(query)) : self.states,
deferred;
if (self.simulateQuery)
{
deferred = $q.defer();
$timeout(function ()
{
deferred.resolve(results);
}, Math.random() * 1000, false);
return deferred.promise;
} else
{
return results;
}
}
function searchTextChange(text)
{
$log.info('Text changed to ' + text);
}
function selectedItemChange(item)
{
$log.info('Item changed to ' + JSON.stringify(item));
}
function loadAll()
{
var allStates = 'Alabama, Alaska, Arizona, Arkansas, California, Colorado, Connecticut, Delaware,\
Florida, Georgia, Hawaii, Idaho, Illinois, Indiana, Iowa, Kansas, Kentucky, Louisiana,\
Maine, Maryland, Massachusetts, Michigan, Minnesota, Mississippi, Missouri, Montana,\
Nebraska, Nevada, New Hampshire, New Jersey, New Mexico, New York, North Carolina,\
North Dakota, Ohio, Oklahoma, Oregon, Pennsylvania, Rhode Island, South Carolina,\
South Dakota, Tennessee, Texas, Utah, Vermont, Virginia, Washington, West Virginia,\
Wisconsin, Wyoming';
return allStates.split(/, +/g).map(function (state)
{
return
{
value: state.toLowerCase(),
display: state
};
});
}
function createFilterFor(query)
{
var lowercaseQuery = angular.lowercase(query);
return function filterFn(state)
{
return (state.value.indexOf(lowercaseQuery) === 0);
};
}
}
})();
Angularjs Material Autocomplete demo's-Angular Material Autocomplete
Once you have a demo running autocomplete file then modify it according to your need.
For bootstrap type ahead another link-bootstrap typeahed
Finally I was able to develop angular autocomplete text box using bootstrap typeahead.
To develop angular bootstrap typeahead with your service returning JSON data below are the steps:
You need to register:
jquery.js
bootstrap.js
angular.js
And to use bootstrap you need to add angular bootstrap dependency javascript file:
ui-bootstrap-tpls-0.14.3.js
In your bundle config register below files:
bundles.Add(new ScriptBundle("~/bundles/cdnjquery").Include("~/Scripts/jquery2.1.4.js"));
bundles.Add(new ScriptBundle("~/bundles/cdnbootstrapjs").Include("~/Scripts/bootstrap.min.js"));
bundles.Add(new ScriptBundle("~/bundles/cdnangularjs").Include("~/Scripts/angular1.4.5.js"));
bundles.Add(new ScriptBundle("~/bundles/cdnangularresourcejs").Include("~/Scripts/angular-resource.js"));
bundles.Add(new ScriptBundle("~/bundles/appjs").Include("~/Scripts/app.js"));
bundles.Add(new ScriptBundle("~/bundles/angularbootstrapjs").Include("~/Scripts/ui-bootstrap-tpls-0.14.3.js"));
bundles.Add(new StyleBundle("~/Content/bootstrapcss").Include("~/Content/bootstrap.css"));
In your cshtml file add below code:
Render scripts and css in your shared or respective .cshml file:
@Styles.Render("~/Content/bootstrapcss")
@Scripts.Render("~/bundles/cdnjquery")
@Scripts.Render("~/bundles/cdnbootstrapjs")
@Scripts.Render("~/bundles/cdnangularjs")
@Scripts.Render("~/bundles/angularbootstrapjs")
@Scripts.Render("~/bundles/appjs")
Write below code in your respective cshtml file:
<h4>Get Quote</h4>
<pre>Model: {{selected | json}}</pre>
<input type="text" ng-model="selected" uib-typeahead="stock.NAME_OF_COMPANY for stock in stocks | filter:$viewValue | limitTo:8" class="form-control">
Now write below code in your app.js file:
var StockMarketApp = angular.module("StockMarketApp", ["ngResource", "ui.bootstrap"]);
StockMarketApp.controller('StockController', function ($scope, $http) {
$scope.stocks = undefined;
$scope.fnGetQuoteDataForAutoComplete = function () {
//$scope.getQuote = 'dhfl';
$http.get("/EquityList/GetStockNamesForAutoComplete")
.success(function (data, status, headers, config) {
$scope.stocks = angular.fromJson(data)
})
.error(function (data, status, headers, config) {
});
};
});
My JSON data contains:
data.SYMBOL
data.NAME_OF_COMPANY
I want to display data.NAME_OF_COMPANY, so if you check in chtml code, I have written:
uib-typeahead="stock.NAME_OF_COMPANY for stock in stocks.
In this way you can create a typeahead using angularjs and bootstrap.
Hope this helps someone who is stumbled upon this like me.