Ajax Pagination with Search and Filter in CodeIgniter


In the earlier CodeIgniter tutorial we have shown the ajax pagination integration process in CodeIgniter. Before you begin we recommend you to read our previous CodeIgniter Ajax pagination tutorial. That guide will help you to understand the basic concept of ajax pagination in CodeIgniter.

In this CodeIgniter tutorial, we’ll extend the Ajax pagination functionality with search and filter. Search and filtering features are commonly used in every data list. Here we’ll show you how to implement live search and filter on the list with Ajax Pagination in CodeIgniter. In our example script, we will fetch the posts data from the database and display in the list. Also, Ajax pagination with search and filter functionality will be added to the post list.

Before you get started, take a look at the folders and files structure of CodeIgniter Ajax Pagination with Search.

codeigniter-ajax-pagination-tutorial-files-structure-codexworld

Database Table Creation

In this example script, we’ll fetch the posts data from the database. The following SQL creates a posts table with some basic fields.

CREATE TABLE `posts` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    `content` text COLLATE utf8_unicode_ci NOT NULL,
    `created` datetime NOT NULL,
    `modified` datetime NOT NULL,
    `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=Active, 0=Inactive',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Ajax Pagination Library

The Ajax_pagination library helps to generate pagination links and get the data without page refresh using jQuery and Ajax. This library (Ajax_pagination.php) need to be placed into the application/libraries/ directory.

<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
 * Pagination Class
 *
 * @package   CodeIgniter
 * @link      http://codeigniter.com/user_guide/libraries/pagination.html
 * 
 * Modified by CodexWorld.com
 * @Ajax pagination functionality has added with this library. 
 * @It will helps to integrate Ajax pagination with loading image in CodeIgniter application.
 * @TutorialLink http://www.codexworld.com/ajax-pagination-in-codeigniter-framework/
 */
class Ajax_pagination{

    var 
$base_url        '';
    var 
$total_rows      '';
    var 
$per_page        10;
    var 
$num_links       =  2;
    var 
$cur_page        =  0;
    var 
$first_link      'First';
    var 
$next_link       '&#187;';
    var 
$prev_link       '&#171;';
    var 
$last_link       'Last';
    var 
$uri_segment     3;
    var 
$full_tag_open   '<div class="pagination">';
    var 
$full_tag_close  '</div>';
    var 
$first_tag_open  '';
    var 
$first_tag_close '&nbsp;';
    var 
$last_tag_open   '&nbsp;';
    var 
$last_tag_close  '';
    var 
$cur_tag_open    '&nbsp;<b>';
    var 
$cur_tag_close   '</b>';
    var 
$next_tag_open   '&nbsp;';
    var 
$next_tag_close  '&nbsp;';
    var 
$prev_tag_open   '&nbsp;';
    var 
$prev_tag_close  '';
    var 
$num_tag_open    '&nbsp;';
    var 
$num_tag_close   '';
    var 
$target          '';
    var 
$anchor_class    '';
    var 
$show_count      true;
    var 
$link_func       'getData';
    var 
$loading         '.loading';

    
/**
     * Constructor
     * @access    public
     * @param    array    initialization parameters
     */
    
function CI_Pagination($params = array()){
        if (
count($params) > 0){
            
$this->initialize($params);        
        }
        
log_message('debug'"Pagination Class Initialized");
    }

    
/**
     * Initialize Preferences
     * @access    public
     * @param    array    initialization parameters
     * @return    void
     */
    
function initialize($params = array()){
        if (
count($params) > 0){
            foreach (
$params as $key => $val){
                if (isset(
$this->$key)){
                    
$this->$key $val;
                }
            }        
        }

        
// Apply class tag using anchor_class variable, if set.
        
if ($this->anchor_class != ''){
            
$this->anchor_class 'class="' $this->anchor_class '" ';
        }
    }

    
/**
     * Generate the pagination links
     * @access    public
     * @return    string
     */    
    
function create_links(){
        
// If our item count or per-page total is zero there is no need to continue.
        
if ($this->total_rows == OR $this->per_page == 0){
           return 
'';
        }

        
// Calculate the total number of pages
        
$num_pages ceil($this->total_rows $this->per_page);

        
// Is there only one page? Hm... nothing more to do here then.
        
if ($num_pages == 1){
            
$info 'Showing : ' $this->total_rows;
            return 
$info;
        }

        
// Determine the current page number.        
        
$CI =& get_instance();    
        if (
$CI->uri->segment($this->uri_segment) != 0){
            
$this->cur_page $CI->uri->segment($this->uri_segment);   
            
// Prep the current page - no funny business!
            
$this->cur_page = (int) $this->cur_page;
        }

        
$this->num_links = (int)$this->num_links;
        if (
$this->num_links 1){
            
show_error('Your number of links must be a positive number.');
        }

        if ( ! 
is_numeric($this->cur_page)){
            
$this->cur_page 0;
        }

        
// Is the page number beyond the result range?
        // If so we show the last page
        
if ($this->cur_page $this->total_rows){
            
$this->cur_page = ($num_pages 1) * $this->per_page;
        }

        
$uri_page_number $this->cur_page;
        
$this->cur_page floor(($this->cur_page/$this->per_page) + 1);

        
// Calculate the start and end numbers. These determine
        // which number to start and end the digit links with
        
$start = (($this->cur_page $this->num_links) > 0) ? $this->cur_page - ($this->num_links 1) : 1;
        
$end   = (($this->cur_page $this->num_links) < $num_pages) ? $this->cur_page $this->num_links $num_pages;

        
// Add a trailing slash to the base URL if needed
        
$this->base_url rtrim($this->base_url'/') .'/';

        
// And here we go...
        
$output '';

        
// SHOWING LINKS
        
if ($this->show_count){
            
$curr_offset $CI->uri->segment($this->uri_segment);
            
$info 'Showing ' . ( $curr_offset ) . ' to ' ;

            if( ( 
$curr_offset $this->per_page ) < ( $this->total_rows -) )
            
$info .= $curr_offset $this->per_page;
            else
            
$info .= $this->total_rows;

            
$info .= ' of ' $this->total_rows ' | ';
            
$output .= $info;
        }

        
// Render the "First" link
        
if  ($this->cur_page $this->num_links){
            
$output .= $this->first_tag_open 
                    
$this->getAJAXlink'' $this->first_link)
                    . 
$this->first_tag_close;
        }

        
// Render the "previous" link
        
if  ($this->cur_page != 1){
            
$i $uri_page_number $this->per_page;
            if (
$i == 0$i '';
            
$output .= $this->prev_tag_open 
                    
$this->getAJAXlink$i$this->prev_link )
                    . 
$this->prev_tag_close;
        }

        
// Write the digit links
        
for ($loop $start -1$loop <= $end$loop++){
            
$i = ($loop $this->per_page) - $this->per_page;    
            if (
$i >= 0){
                if (
$this->cur_page == $loop){
                    
$output .= $this->cur_tag_open.$loop.$this->cur_tag_close// Current page
                
}else{
                    
$n = ($i == 0) ? '' $i;
                    
$output .= $this->num_tag_open
                        
$this->getAJAXlink$n$loop )
                        . 
$this->num_tag_close;
                }
            }
        }

        
// Render the "next" link
        
if ($this->cur_page $num_pages){
            
$output .= $this->next_tag_open 
                
$this->getAJAXlink$this->cur_page $this->per_page $this->next_link )
                . 
$this->next_tag_close;
        }

        
// Render the "Last" link
        
if (($this->cur_page $this->num_links) < $num_pages){
            
$i = (($num_pages $this->per_page) - $this->per_page);
            
$output .= $this->last_tag_open $this->getAJAXlink$i$this->last_link ) . $this->last_tag_close;
        }

        
// Kill double slashes.  Note: Sometimes we can end up with a double slash
        // in the penultimate link so we'll kill all double slashes.
        
$output preg_replace("#([^:])//+#""\\1/"$output);

        
// Add the wrapper HTML if exists
        
$output $this->full_tag_open.$output.$this->full_tag_close;
        
?>
        <script>
        function getData(page){  
            $.ajax({
                method: "POST",
                url: "<?php echo $this->base_url?>"+page,
                data: { page: page },
                beforeSend: function(){
                    $('<?php echo $this->loading?>').show();
                },
                success: function(data){
                    $('<?php echo $this->loading?>').hide();
                    $('<?php echo $this->target?>').html(data);
                }
            });
        }
        </script>
        <?php
        
return $output;
    }

    function 
getAJAXlink($count$text) {
        
$pageCount $count?$count:0;
        return 
'<a href="javascript:void(0);"' $this->anchor_class ' onclick="'.$this->link_func.'('.$pageCount.')">'$text .'</a>';
    }
}

Controller (Posts.php)

The Posts controller contains of 3 functions __construct(), index(), and ajaxPaginationData().
__construct() – Post model and Ajax_pagination library is loaded in this function. Also, the per page data limit is set into $this->perPage variable.
index() – The posts data is fetched using Post model and passes to the view. The pagination library is configured and initiated to display the pagination links.
ajaxPaginationData() – Like the index() function ajaxPaginationData() doing the same. But this method is loaded via Ajax by clicking the pagination links.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * Posts Management class created by CodexWorld
 */
class Posts extends CI_Controller {
    
    function 
__construct() {
        
parent::__construct();
        
$this->load->model('post');
        
$this->load->library('Ajax_pagination');
        
$this->perPage 2;
    }
    
    public function 
index(){
        
$data = array();
        
        
//total rows count
        
$totalRec count($this->post->getRows());
        
        
//pagination configuration
        
$config['target']      = '#postList';
        
$config['base_url']    = base_url().'posts/ajaxPaginationData';
        
$config['total_rows']  = $totalRec;
        
$config['per_page']    = $this->perPage;
        
$config['link_func']   = 'searchFilter';
        
$this->ajax_pagination->initialize($config);
        
        
//get the posts data
        
$data['posts'] = $this->post->getRows(array('limit'=>$this->perPage));
        
        
//load the view
        
$this->load->view('posts/index'$data);
    }
    
    function 
ajaxPaginationData(){
        
$conditions = array();
        
        
//calc offset number
        
$page $this->input->post('page');
        if(!
$page){
            
$offset 0;
        }else{
            
$offset $page;
        }
        
        
//set conditions for search
        
$keywords $this->input->post('keywords');
        
$sortBy $this->input->post('sortBy');
        if(!empty(
$keywords)){
            
$conditions['search']['keywords'] = $keywords;
        }
        if(!empty(
$sortBy)){
            
$conditions['search']['sortBy'] = $sortBy;
        }
        
        
//total rows count
        
$totalRec count($this->post->getRows($conditions));
        
        
//pagination configuration
        
$config['target']      = '#postList';
        
$config['base_url']    = base_url().'posts/ajaxPaginationData';
        
$config['total_rows']  = $totalRec;
        
$config['per_page']    = $this->perPage;
        
$config['link_func']   = 'searchFilter';
        
$this->ajax_pagination->initialize($config);
        
        
//set start and limit
        
$conditions['start'] = $offset;
        
$conditions['limit'] = $this->perPage;
        
        
//get posts data
        
$data['posts'] = $this->post->getRows($conditions);
        
        
//load the view
        
$this->load->view('posts/ajax-pagination-data'$datafalse);
    }
}

If you notice on pagination configuration, a function (searchFilter) is specified in link_func. This user defined function will be called on each pagination link, that helps to pass the search and filter request.

Model (Post.php)

The Post model is used to fetch the posts data from the database and returns data based on the conditions passed by $params array.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class 
Post extends CI_Model{
    
/*
     * get rows from the posts table
     */
    
function getRows($params = array()){
        
$this->db->select('*');
        
$this->db->from('posts');
        
//filter data by searched keywords
        
if(!empty($params['search']['keywords'])){
            
$this->db->like('title',$params['search']['keywords']);
        }
        
//sort data by ascending or desceding order
        
if(!empty($params['search']['sortBy'])){
            
$this->db->order_by('title',$params['search']['sortBy']);
        }else{
            
$this->db->order_by('id','desc');
        }
        
//set start and limit
        
if(array_key_exists("start",$params) && array_key_exists("limit",$params)){
            
$this->db->limit($params['limit'],$params['start']);
        }elseif(!
array_key_exists("start",$params) && array_key_exists("limit",$params)){
            
$this->db->limit($params['limit']);
        }
        
//get records
        
$query $this->db->get();
        
//return fetched data
        
return ($query->num_rows() > 0)?$query->result_array():FALSE;
    }

}

View (posts/)

Two view files is used, index.php and ajax-pagination-data.php.
index.php:
The jQuery is used for Ajax pagination and search, so jQuery library need to be loaded first.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

On pagination links click searchFilter() JavaScript function is loaded. This function gets the values from search field and filter drop-down and sends to ajaxPaginationData() of Posts controller via Ajax. Once the response is received, the respective posts data is displayed in the post list.

<script>
function searchFilter(page_num) {
    page_num = page_num?page_num:0;
    var keywords = $('#keywords').val();
    var sortBy = $('#sortBy').val();
    $.ajax({
        type: 'POST',
        url: '<?php echo base_url(); ?>posts/ajaxPaginationData/'+page_num,
        data:'page='+page_num+'&keywords='+keywords+'&sortBy='+sortBy,
        beforeSend: function () {
            $('.loading').show();
        },
        success: function (html) {
            $('#postList').html(html);
            $('.loading').fadeOut("slow");
        }
    });
}
</script>

On Post controller load, some specified number of posts is listed with search input and filter dropdown. To display the pagination link, create_links() function is used from Pagination library ($this->ajax_pagination->create_links()). The loading div is used to display loader image on post loading.

<div class="container">
    <h1>Ajax Pagination with Search in CodeIgniter</h1>
    <div class="row">
        <div class="post-search-panel">
            <input type="text" id="keywords" placeholder="Type keywords to filter posts" onkeyup="searchFilter()"/>
            <select id="sortBy" onchange="searchFilter()">
                <option value="">Sort By</option>
                <option value="asc">Ascending</option>
                <option value="desc">Descending</option>
            </select>
        </div>
        <div class="post-list" id="postList">
            <?php if(!empty($posts)): foreach($posts as $post): ?>
                <div class="list-item"><a href="javascript:void(0);"><h2><?php echo $post['title']; ?></h2></a></div>
            <?php endforeach; else: ?>
            <p>Post(s) not available.</p>
            <?php endif; ?>
            <?php echo $this->ajax_pagination->create_links(); ?> </div> <div class="loading" style="display: none;"><div class="content"><img src="<?php echo base_url().'assets/images/loading.gif'?>"/></div></div> </div> </div>

ajax-pagination-data.php:
When pagination links are clicked, this view is loaded and it displays only the posts data with pagination links.

<?php if(!empty($posts)): foreach($posts as $post): ?>
    <div class="list-item"><a href="javascript:void(0);"><h2><?php echo $post['title']; ?></h2></a></div>
<?php endforeach; else: ?>
<p>Post(s) not available.</p>
<?php endif; ?>
<?php 
echo $this->ajax_pagination->create_links(); ?>

Are you want to get implementation help, or modify or extend the functionality of this script? Submit paid service request

Recommended Tutorials For You

2 Comments

  1. Matteus Sousa Said...

Leave a reply