Previously we already discussed below Auto Complete components:
- Ajax Based Multiselect JQuery Autocomplete Control in ASP.Net
- AutoComplete Component in Visualforce using JQueryUI
In this article, we will be creating TypeAhead Directive (Auto Complete) again in Salesforce However this time we will use AngularJs. Why we are using AngularJS ? We discussed already in one of article.
Getting Remote Data in JSON format using AJAX from:
To get data from remote source, we are using same code “Visualforce Account_JSON” and “Controller AccountJSONCreator ” explained in this article. Only thing I have added in wrapper class is ID field.
Other than AngularJs, we are also using Bootstrap in this article to make slick UI.
Angular Directive :
Directive is great way of declaring your own component and re-use throughout page. write once and re-use every where. Our directive will look like :
<typeahead title="AccName" subtitle="BillingCity" displaykey="AccName" retkey="AccId" modelret="valRet" modeldisplay="valDis" />
typeAhead – Name of Directive
title – After Ajax, value from JSON to display in first line
subtitle – After Ajax, value from JSON to display in second line
displaykey – When item is selected, which JSON attribute to display (Most of time same as title)
retkey – After Selecting value, what should be stored hidden (Something like ID)
modelret – Hidden field value returned by directive
modeldisplay – selected value returned by directive
Live Demo :
Complete Code :
Visualforce TypeAheadDemo :
<apex:page showHeader="false" sidebar="false"> <apex:includeScript value="{!$Resource.Angular}"/> <apex:stylesheet value="{!URLFOR($Resource.BootStrap3, 'bootstrap-3.1.1-dist/css/bootstrap.min.css')}"/> <div ng-app="app1"> <div class="well-lg well"> <h1> Type Ahead Example in AngularJs | Shivasoft </h1> </div> <div ng-controller="ItemCtrl" class="container"> Angular Lookup : <div style="width:200px;"> <typeahead title="AccName" subtitle="BillingCity" displaykey="AccName" retkey="AccId" modelret="valRet" modeldisplay="valDis" /> </div> <br /> <b> Value Selected</b> {{valDis}} <br /> <b> Selected Id (Hidden) </b> {{valRet}} </div> </div> <script> var myApp = angular.module('app1',[]); myApp.controller('ItemCtrl', ['$scope','$templateCache','$http', function($scope,$templateCache,$http) { }]); myApp.directive('typeahead', function($timeout,$http) { return { restrict: 'AEC', scope: { title: '@', retkey: '@', displaykey:'@', modeldisplay:'=', subtitle: '@', modelret: '=' }, link: function(scope, elem, attrs) { scope.current = 0; scope.selected = false; scope.da = function(txt){ scope.ajaxClass = 'loadImage'; $http({method: 'Get', url: 'Account_JSON?AccName='+txt}). success(function(data, status) { scope.TypeAheadData = data; scope.ajaxClass = ''; }) ; } scope.handleSelection = function(key,val) { scope.modelret = key; scope.modeldisplay = val; scope.current = 0; scope.selected = true; } scope.isCurrent = function(index) { return scope.current == index; } scope.setCurrent = function(index) { scope.current = index; } }, template: '<input type="text" ng-model="modeldisplay" ng-KeyPress="da(modeldisplay)" ng-keydown="selected=false"'+ 'style="width:100%;" ng-class="ajaxClass">'+ '<div class="list-group table-condensed overlap" ng-hide="!modeldisplay.length || selected" style="width:100%">'+ '<a href="javascript:void();" class="list-group-item noTopBottomPad" ng-repeat="item in TypeAheadData|filter:model track by $index" '+ 'ng-click="handleSelection(item[retkey],item[displaykey])" style="cursor:pointer" '+ 'ng-class="{active:isCurrent($index)}" '+ 'ng-mouseenter="setCurrent($index)">'+ ' {{item[title]}}<br />'+ '<i>{{item[subtitle]}} </i>'+ '</a> '+ '</div>'+ '</input>' }; }); </script> <style> .noTopBottomPad { padding-top : 2px !important; padding-bottom : 2px !important; } .overlap {position: absolute !important; z-index: 900 !important; width: inherit !important ;} .loadImage { background: white url('{!URLFOR($Resource.AutoCompleteWithModal, 'AjaxLoad.gif')}') right center no-repeat; } </style> </apex:page>
Visualforce Account_JSON (To Query and get data in JSON format) :
<apex:page Controller="AccountJSONCreator" contentType="application/x-JavaScript; charset=utf-8" showHeader="false" standardStylesheets="false" sidebar="false"> {!JSON} </apex:page>
Controller AccountJSONCreator :
public with sharing class AccountJSONCreator { public String getJSON() { String AccountName = Apexpages.currentPage().getParameters().get('AccName'); List<AccountWrapper> wrp = new List<AccountWrapper>(); for (Account a : [Select a.Id, a.Website, a.Name, a.BillingCountry, a.BillingCity From Account a WHERE Name Like : '%'+AccountName+'%' ]) { AccountWrapper w = new AccountWrapper (a.Name, nullToBlank (a.BillingCountry), nullToBlank (a.BillingCity), a.Id); wrp.add(w); } return JSON.serialize(wrp); } public String nullToBlank(String val) { return val == null ?'':val; } public class AccountWrapper { String AccName,BillingCountry,BillingCity,AccId; public AccountWrapper(String aName, String bCountry, String bCity, String i) { AccName = aName; BillingCountry = bCountry; BillingCity = bCity; AccId = i ; } } static testMethod void AccountJSONCreatorTest() { AccountJSONCreator obj = new AccountJSONCreator(); obj.getJSON(); } }
Leave a Reply