Steps
to Implement AutoComplete/AutoTypeAhead using Lightning Component and
Generic Search Term (re-usable code for searching within any
Object/Term):
1) Create My Domain. (SetUp->Domain Management->My Domain)
2) Create a class "AutoTypeAheadController" with Aura enabled method (Re-usable method for searching a term within any SObject)
3) Upload Static Resources:
a) bootstrap.min.css (Static Resource Name: BootStrapCss)
Link: http://developer.salesforcefoundation.org/bootstrap-sf1/
b) jquery-1.11.3.min.js (Static Resource Name: jqueryjs)
Link: https://jquery.com/download/
c) jquery-ui.css (Static Resource Name: jqueryuicss)
Link: https://jqueryui.com/download/all/
d) jquery-ui.min.js (Static Resource Name: jqueryuijs)
Link: https://jqueryui.com/download/all/
4) Create Lightning Component "AutoTypeAhead".
5) Create Lightning App "AutoTypeAheadApp".
6) If your Org doesnt have namespace then use the following URL to access the Lightning App:
https://<<Domain Name>>.lightning.force.com/c/AutoTypeAheadApp.app
If your Org has a namespace then use the following URL to access the Lightning App:
https://<<>Domain Name>.lightning.force.com/<<NameSpace>>/AutoTypeAheadApp.app
Code Details:
************************************************************************************************************
Class: AutoTypeAheadController
************************************************************************************************************
global class AutoTypeAheadController {
@AuraEnabled
global static SObject[] autoSearch(map<string,string> request){
/*
Purpose: this function will be called from the lightning component,
This will provide search result (SOSL) for any single object.
request contains the following string key-value pairs
@find: the actual string, user would search for
@sobject: api name of sobject in which search would occur
@fields: csv of the api names of the field that search would return
@where: where clause used in SOSL
@limit: limit clause used in SOSL
@return: the function would return list of sobject
Example:
map<String, String> request
= new Map<String, String>
{'find' => 'test', 'sobject' => 'Account', 'fields' => 'Id, Name', 'where' => 'Status=Active', 'limit' => 25};
*/
String find = String.escapeSingleQuotes(request.get('find'));
String sobject_name = request.get('sobject');
String fields = request.containsKey('fields')? request.get('fields') : 'Name';
String where_clause = request.containsKey('where') ? ' WHERE ' + request.get('where') : '';
String limit_clause = request.containsKey('limit') ? ' LIMIT ' + request.get('limit') : '';
String sosl = 'FIND \'%STR%*\'IN NAME FIELDS RETURNING %SOBJECT% (Id, %FIELDS% %WHERE% %LIMIT%)';
sosl = sosl.replace('%WHERE%', where_clause);
sosl = sosl.replace('%LIMIT%', limit_clause);
sosl = sosl.replace('%STR%', find).replace('%SOBJECT%', sobject_name).replace('%FIELDS%', fields);
SObject[] search_result = new SObject[0];
for(sobject s :search.query(sosl)[0]){
if(String.valueOf(s.get('Name')).containsIgnoreCase(find)) {
search_result.add(s); }
}
return search_result;
}
}
************************************************************************************************************
************************************************************************************************************
************************************************************************************************************
Lightning Component: AutoTypeAhead
************************************************************************************************************
*************
Component:
*************
<aura:component controller="AutoTypeAheadController" implements="flexipage:availableForAllPageTypes,force:appHostable">
<aura:attribute name="sObjectType" required="true" type="String" description="Name of the sObject that will be filtered" />
<aura:attribute name="fields" type="String[]" default="" description="List of fields to get with each record"/>
<aura:attribute name="limit" type="String" default="10" description="Limits the number returned to this value" />
<aura:attribute name="inputLabel" type="String" default="Find" description="Label for text input"/>
<aura:attribute name="ready" type="Boolean" default="false" description="Used to check if resources have been loaded"/>
<aura:registerEvent name="autotypeaheadEvt" type="c:autotypeaheadEvt"/>
<ltng:require scripts="/resource/jqueryjs,/resource/jqueryuijs"
styles="/resource/jqueryuicss,/resource/BootStrapCss"
afterScriptsLoaded="{!c.init}"
/>
<div>
<label>Search for {!v.sObjectType}: </label>
<input id="searchTerm" class="AutoTypeAhead" type="text" />
</div>
</aura:component>
*************
*************
*************
Controller:
*************
({
init: function(component, event, helper) {
if (typeof jQuery !== "undefined" && typeof $j === "undefined") {
$j = jQuery.noConflict(true);;
}
component.set("v.ready", true);
helper.initHandlers(component);
}
})
*************
*************
*************
Helper:
*************
({
initHandlers: function(component) {
var ready = component.get("v.ready");
if (ready === false) {
return;
}
var ctx = component.getElement();
$j(".AutoTypeAhead", ctx).autocomplete({
minLength: 2,
delay: 500,
source: function(request, response) {
var action = component.get("c.autoSearch");
var fieldsToGet = component.get("v.fields");
action.setParams({
"request":{
"sobject": component.get("v.sObjectType"),
"find": request.term,
"fields": fieldsToGet.join(),
"limit": component.get("v.limit")}
});
action.setCallback(this, function(a) {
var suggestions = a.getReturnValue();
var responseRes = a.getState();
if (responseRes === "ERROR") {
var errors = a.getError();
if (errors) {
if (errors[0] && errors[0].message) {
console.log("Error message: " + errors[0].message);
}
} else {
console.log("Unknown error");
}
}
if(responseRes === "SUCCESS")
{
//console.log("Output:"+JSON.stringify(suggestions));
suggestions.forEach(function(s) {
s["label"] = s.Name,
s["value"] = s.Id
});
}
response(suggestions);
});
$A.run(function() {
$A.enqueueAction(action);
});
},
select: function(event, ui) {
event.preventDefault();
var ctx = component.getElement();
$j(".AutoTypeAhead", ctx).val(ui.item.label);
var selectionEvent = component.getEvent("autotypeaheadEvt");
selectionEvent.setParams({
selectedOption: ui.item
});
selectionEvent.fire();
}
});
}
})
*************
*************
2) Create a class "AutoTypeAheadController" with Aura enabled method (Re-usable method for searching a term within any SObject)
3) Upload Static Resources:
a) bootstrap.min.css (Static Resource Name: BootStrapCss)
Link: http://developer.salesforcefoundation.org/bootstrap-sf1/
b) jquery-1.11.3.min.js (Static Resource Name: jqueryjs)
Link: https://jquery.com/download/
c) jquery-ui.css (Static Resource Name: jqueryuicss)
Link: https://jqueryui.com/download/all/
d) jquery-ui.min.js (Static Resource Name: jqueryuijs)
Link: https://jqueryui.com/download/all/
4) Create Lightning Component "AutoTypeAhead".
5) Create Lightning App "AutoTypeAheadApp".
6) If your Org doesnt have namespace then use the following URL to access the Lightning App:
https://<<Domain Name>>.lightning.force.com/c/AutoTypeAheadApp.app
If your Org has a namespace then use the following URL to access the Lightning App:
https://<<>Domain Name>.lightning.force.com/<<NameSpace>>/AutoTypeAheadApp.app
Code Details:
************************************************************************************************************
Class: AutoTypeAheadController
************************************************************************************************************
global class AutoTypeAheadController {
@AuraEnabled
global static SObject[] autoSearch(map<string,string> request){
/*
Purpose: this function will be called from the lightning component,
This will provide search result (SOSL) for any single object.
request contains the following string key-value pairs
@find: the actual string, user would search for
@sobject: api name of sobject in which search would occur
@fields: csv of the api names of the field that search would return
@where: where clause used in SOSL
@limit: limit clause used in SOSL
@return: the function would return list of sobject
Example:
map<String, String> request
= new Map<String, String>
{'find' => 'test', 'sobject' => 'Account', 'fields' => 'Id, Name', 'where' => 'Status=Active', 'limit' => 25};
*/
String find = String.escapeSingleQuotes(request.get('find'));
String sobject_name = request.get('sobject');
String fields = request.containsKey('fields')? request.get('fields') : 'Name';
String where_clause = request.containsKey('where') ? ' WHERE ' + request.get('where') : '';
String limit_clause = request.containsKey('limit') ? ' LIMIT ' + request.get('limit') : '';
String sosl = 'FIND \'%STR%*\'IN NAME FIELDS RETURNING %SOBJECT% (Id, %FIELDS% %WHERE% %LIMIT%)';
sosl = sosl.replace('%WHERE%', where_clause);
sosl = sosl.replace('%LIMIT%', limit_clause);
sosl = sosl.replace('%STR%', find).replace('%SOBJECT%', sobject_name).replace('%FIELDS%', fields);
SObject[] search_result = new SObject[0];
for(sobject s :search.query(sosl)[0]){
if(String.valueOf(s.get('Name')).containsIgnoreCase(find)) {
search_result.add(s); }
}
return search_result;
}
}
************************************************************************************************************
************************************************************************************************************
************************************************************************************************************
Lightning Component: AutoTypeAhead
************************************************************************************************************
*************
Component:
*************
<aura:component controller="AutoTypeAheadController" implements="flexipage:availableForAllPageTypes,force:appHostable">
<aura:attribute name="sObjectType" required="true" type="String" description="Name of the sObject that will be filtered" />
<aura:attribute name="fields" type="String[]" default="" description="List of fields to get with each record"/>
<aura:attribute name="limit" type="String" default="10" description="Limits the number returned to this value" />
<aura:attribute name="inputLabel" type="String" default="Find" description="Label for text input"/>
<aura:attribute name="ready" type="Boolean" default="false" description="Used to check if resources have been loaded"/>
<aura:registerEvent name="autotypeaheadEvt" type="c:autotypeaheadEvt"/>
<ltng:require scripts="/resource/jqueryjs,/resource/jqueryuijs"
styles="/resource/jqueryuicss,/resource/BootStrapCss"
afterScriptsLoaded="{!c.init}"
/>
<div>
<label>Search for {!v.sObjectType}: </label>
<input id="searchTerm" class="AutoTypeAhead" type="text" />
</div>
</aura:component>
*************
*************
*************
Controller:
*************
({
init: function(component, event, helper) {
if (typeof jQuery !== "undefined" && typeof $j === "undefined") {
$j = jQuery.noConflict(true);;
}
component.set("v.ready", true);
helper.initHandlers(component);
}
})
*************
*************
*************
Helper:
*************
({
initHandlers: function(component) {
var ready = component.get("v.ready");
if (ready === false) {
return;
}
var ctx = component.getElement();
$j(".AutoTypeAhead", ctx).autocomplete({
minLength: 2,
delay: 500,
source: function(request, response) {
var action = component.get("c.autoSearch");
var fieldsToGet = component.get("v.fields");
action.setParams({
"request":{
"sobject": component.get("v.sObjectType"),
"find": request.term,
"fields": fieldsToGet.join(),
"limit": component.get("v.limit")}
});
action.setCallback(this, function(a) {
var suggestions = a.getReturnValue();
var responseRes = a.getState();
if (responseRes === "ERROR") {
var errors = a.getError();
if (errors) {
if (errors[0] && errors[0].message) {
console.log("Error message: " + errors[0].message);
}
} else {
console.log("Unknown error");
}
}
if(responseRes === "SUCCESS")
{
//console.log("Output:"+JSON.stringify(suggestions));
suggestions.forEach(function(s) {
s["label"] = s.Name,
s["value"] = s.Id
});
}
response(suggestions);
});
$A.run(function() {
$A.enqueueAction(action);
});
},
select: function(event, ui) {
event.preventDefault();
var ctx = component.getElement();
$j(".AutoTypeAhead", ctx).val(ui.item.label);
var selectionEvent = component.getEvent("autotypeaheadEvt");
selectionEvent.setParams({
selectedOption: ui.item
});
selectionEvent.fire();
}
});
}
})
*************
*************
*************
Event:
*************
Event:
*************
<aura:event type="COMPONENT"> <aura:attribute name="selectedOption" type="Object"/></aura:event>
**************
**************
*************
Renderer:
*************
({
afterRender : function(component, helper) {
this.superAfterRender();
helper.initHandlers(component);
}
})
*************
*************
************************************************************************************************************
************************************************************************************************************
************************************************************************************************************
Lightning App: AutoTypeAheadApp
************************************************************************************************************
*************
Application:
*************
<aura:application implements="force:appHostable">
<div class="container-fluid">
<div class="jumbotron">
<h1>Auto-Complete Lightning Component</h1>
</div>
<div class="row">
<div class="form-group text-center">
<c:AutoTypeAhead sObjectType="Account"
autotypeaheadEvt="{!c.handleAutocomplete}"
fields="Name,AccountNumber"
/>
</div>
</div>
<div id="result"></div>
</div>
</aura:application>
*************
*************
*************
Controller:
*************
({
handleAutocomplete : function(component, event, helper) {
var so = event.getParam("selectedOption");
document.getElementById("result").innerHTML = 'Selected:' + so.Name;
}
})
*************
*************
************************************************************************************************************
************************************************************************************************************
*************
Renderer:
*************
({
afterRender : function(component, helper) {
this.superAfterRender();
helper.initHandlers(component);
}
})
*************
*************
************************************************************************************************************
************************************************************************************************************
************************************************************************************************************
Lightning App: AutoTypeAheadApp
************************************************************************************************************
*************
Application:
*************
<aura:application implements="force:appHostable">
<div class="container-fluid">
<div class="jumbotron">
<h1>Auto-Complete Lightning Component</h1>
</div>
<div class="row">
<div class="form-group text-center">
<c:AutoTypeAhead sObjectType="Account"
autotypeaheadEvt="{!c.handleAutocomplete}"
fields="Name,AccountNumber"
/>
</div>
</div>
<div id="result"></div>
</div>
</aura:application>
*************
*************
*************
Controller:
*************
({
handleAutocomplete : function(component, event, helper) {
var so = event.getParam("selectedOption");
document.getElementById("result").innerHTML = 'Selected:' + so.Name;
}
})
*************
*************
************************************************************************************************************
************************************************************************************************************
No comments:
Post a Comment