Sencha Touch 2 Autocomplete AJAX Example using Java Servlet

The Ext package has the ComboBox which is an extension of the Text field but I couldn't find anything similar in case of Sencha Touch where a Text field can give suggestions from the Server as the user types into the field. In this example we send an ajax request to the Java Servlet on every key stroke to get the results back and display it on a list that is floating next to our input text box. If you already have static data then you can change that to filter the store attached to the list.


Sencha Touch 2 Autocomplete AJAX Example using Java Servlet

Application HTML file - autoComplete.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="java.io.*" %>    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="robots" content="noindex,nofollow"/>
<title>Programmers sample guide, help is on the way</title>
<link rel="stylesheet" href="/sencha-touch/resources/css-debug/sencha-touch.css" type="text/css">
<link rel="stylesheet" href="/resources/themes/app-master.css" type="text/css" />
<style>
.myClass {
    border-style: dashed;
}
</style>
<script src="/resources/scripts/mysamplecode.js" type="text/javascript"></script>
<script type="text/javascript" src="/sencha-touch/sencha-touch-all-debug.js"></script>
<script type="text/javascript">

Ext.Loader.setConfig({ 
 enabled: true 
});

Ext.application({
    
 name: 'MyApp',
 appFolder: '/Sencha_Touch/app/autoComplete',
 
 requires: [
               'MyApp.view.MyPanel',
               'MyApp.view.MyList',
               ], 
               
    views : ['MyPanel'],           
    controllers: ['AutoCompleteDemo'],
    
    launch: function() {
     console.log('Application launch');
     Ext.create('Ext.Container', {
      fullscreen: true,
      layout: 'vbox',
         items: [{
          flex: 1,
          xtype: 'myPanel'
            }]
     });
    }
    
});

</script>
</head>

<body>
</body>
</html>

Model - Country.js

Ext.define('MyApp.model.Country', {
    extend: 'Ext.data.Model',
    config: {
     fields: [
              'code',
              'name'
              ]
    }
});

Store - Countries.js

Ext.define('MyApp.store.Countries', {
    extend: 'Ext.data.Store',
    
    config: {
     model: 'MyApp.model.Country',
     autoLoad: false,
     pageSize: 9999,
     
     proxy: {
         type: 'ajax',
         url: '../CountrySearch',
         reader: {
             type: 'json',
             rootProperty: 'countries',
             successProperty: 'success'
         },
   }
    }
});

Panel View with Country field - MyPanel.js

Ext.define('MyApp.view.MyPanel', {
    extend: 'Ext.dataview.List',
    alias : 'widget.myPanel',
    
    config: {
      
     //Just a input text field for out autocomplete
  items: [{
      xtype: 'textfield',
      name: 'inputText',
      labelWidth: 150,
      width: 450,
      label: 'Select a Country',
      itemId: 'searchBox'
  }]   

    } 

});

Auto Complete Dropdown List - MyList.js

//displays a list of countries in a floating panel
Ext.define('MyApp.view.MyList', {
    extend: 'Ext.dataview.List',
    alias : 'widget.myList',
    
    config: {
     store : 'Countries',
     left: 0,
        top: 0,
        hideOnMaskTap: true,
        width: 300,
        height: "50%",
        cls: 'myClass',
        
     itemTpl:  '<div class="myContent">'+ 
         '<div><b>{name}</b> ({code})</div>' +
         '</div>',
    
     emptyText: '<div class="myContent">No Matching Countries</div>',
    
    } 
});

Application Controller - AutoCompleteDemo.js

Ext.define('MyApp.controller.AutoCompleteDemo', {
 extend : 'Ext.app.Controller',

 config: {
  profile: Ext.os.deviceType.toLowerCase(),
  stores : ['Countries'],
  models : ['Country'],
  
  control: {
   'myPanel': {
    activate: 'onActivate'
   },
   'myPanel textfield[itemId=searchBox]' : {
    //clear the input text box
    clearicontap : 'onClearSearch',
    //on every key stroke
    keyup: 'onSearchKeyUp'
   },
   'myList': {
    //select the country
    itemtap: 'onSelectRow'
   }
  }  

 },

 onActivate: function() {
  //console.log('Main container is active');
 },

 onSearchKeyUp: function(searchField) {
  queryString = searchField.getValue();
  //console.log(this,'Please search by: ' + queryString);
  
  //create and display the floating list 
  var myList = Ext.Viewport.down('myList');
  if(!myList){
   myList = Ext.widget('myList');
   myList.showBy(searchField, "tr-br?");
  } 
  //just display it
  else {
   myList.setHidden(false);
  }
  
  //load data into the list store based on the query
  var store = Ext.getStore('Countries');
  store.load({
   params: {
    'queryString': queryString
   },
   callback: function(records, operation, success) {
    //console.log(success);
   }
  });
  
  

 },

 onClearSearch: function() {
  //console.log('Clear icon is tapped');
  
  //remove all data from the store
  var store = Ext.getStore('Countries');
  store.removeAll();
  
  //hide out floating list
  var myList = Ext.Viewport.down('myList');
  myList.setHidden(true);
  
 },
 
 onSelectRow: function(view, index, target, record, event) {
  //console.log('Clicked on a Row');
  //get reference to the panel
  var myPanel = Ext.Viewport.down('myPanel');
  //set the text field value 
  myPanel.getComponent('searchBox').setValue(record.get('name'));
  //clear the drop down list
  this.onClearSearch();
 },

 init: function() {
  //console.log('Controller initialized');
 }

});

Java Servlet - CountrySearch.java

package com.as400samplecode;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import com.as400samplecode.util.Country;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

public class CountrySearch extends HttpServlet {
 private static final long serialVersionUID = 1L;

 public CountrySearch() {
  super();
 }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) 
 throws ServletException, IOException {
  doPost(request,response);
 }

 protected void doPost(HttpServletRequest request, HttpServletResponse response) 
 throws ServletException, IOException {

  String queryString = request.getParameter("queryString");
  
  PrintWriter out = response.getWriter();
  response.setContentType("text/html");
  
  ArrayList<Country> countryList = getItems(queryString);
  
  Gson gson = new Gson();
  JsonObject myObj = new JsonObject();
  myObj.addProperty("success", true);
  myObj.add("countries", gson.toJsonTree(countryList));
  out.println(myObj.toString());
  out.close();


 }
 
 private ArrayList<Country> getItems(String queryString) {  
  
  Connection conn = null;             
  PreparedStatement stmt = null;      
  String sql = null;
  
  ArrayList<Country> countryList = new ArrayList<Country>();    
  
  try {       
   Context ctx = (Context) new InitialContext().lookup("java:comp/env");
   conn = ((DataSource) ctx.lookup("jdbc/mysql")).getConnection(); 

   sql = "Select * from country where name like ? order by name,code "; 
   stmt = conn.prepareStatement(sql);
   stmt.setString(1, queryString.trim() + "%"); 
   
   ResultSet rs = stmt.executeQuery();  
   
   while(rs.next()){ 
    Country country = new Country();
    country.setCode(rs.getString("code").trim());
    country.setName(rs.getString("name").trim());
    countryList.add(country);
   }                                                                          

   rs.close();                                                                
   stmt.close();                                                              
   stmt = null;                                                               


   conn.close();                                                              
   conn = null;                                                    

  }                                                                
  catch(Exception e){System.out.println(e);}                       

  finally {                                                        
   
   if (stmt != null) {                                             
    try {                                                          
     stmt.close();                                                 
    } catch (SQLException sqlex) {                                 
     // ignore -- as we can't do anything about it here            
    }                                                              

    stmt = null;                                             
   }                                                         

   if (conn != null) {                                       
    try {                                                    
     conn.close();                                           
    } catch (SQLException sqlex) {                           
     // ignore -- as we can't do anything about it here      
    }                                                        

    conn = null;                                             
   }                                                         
  }               

  return countryList;

 }   

}

3 comments :

  1. I have to say, this is a fantastic example. Excellent Work. It was so easy to follow.

    What is the best way to hide the search panel? If if use the blur() event of the text field then you cannot scroll through the result as the list has been hidden when you close the ipad keyboard.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete