Paginación Ajax en CodeIgniter

CodeIgniter cuenta con una librería para la paginación por defecto. Pero en muchas ocasiones necesitamos implementar una página basada en Ajax en CodeIgniter, ya que proporciona al usuario una mejor experiencia de navegación. En este tutorial veremos cómo crear una paginación Ajax en el framework CodeIgniter.

Vamos a modificar la librería de paginación de CodeIgniter para integrar la funcionalidad de Ajax en nuestra aplicación. Este cambio nos traerá nuevas mejoras, como:

Mostrar una imagen mientras que la información carga
Añadir funciones personalizadas a los enlaces de cada una de las páginas
Definir un selector para cargar los datos de la paginación
y mucho más...

Para que me entendáis mejor, he creado un script de ejemplo. En este código, extraeremos la información de la base de datos y los mostraremos en la vista, junto a los enlaces de la paginación. Una vez se hace clic en alguno de estos enlaces, se extraerá más información de la base de datos y se mostrará en lugar de la antigua información. También aparecerá una imagen (loader) mientras que la petición se está procesando.

Antes de empezar, vamos a echar un vistazo a la estructura de carpetas y ficheros del script de ejemplo:

codeigniter
> application
>> controllers
>>> Posts.php
>> libraries
>>> Ajax_pagination.php
>> models
>>> Post.php
>> views
>>> posts
>>>> ajax-pagination-data.php
>>>> index.php
> assets
>> images
>>> loading.gif

Creación de la tabla de la base de datos

Crearemos una tabla (posts) en nuestra base de datos.

Codigo

Librería Pagination

La librería de paginación nos ayuda a generar los enlaces para la paginación. Solo debes definir las opciones para la configuración y llamar a la función create_links(). He copiado la librería para la paginación de CodeIgniter, la he renombrado como Ajax_pagination y, por último, le he añadido el código necesario para que funcione con Ajax. Para ello, crea un nuevo fichero llamado Ajax_pagination.php, y copia y pega el código de más abajo en dicho fichero que debes alojar en la carpeta application/libraries.

<?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        = ''; // The page we are linking to
    var $total_rows      = ''; // Total number of items (database results)
    var $per_page        = 10; // Max number of items you want shown per page
    var $num_links       =  2; // Number of "digit" links to show before/after the currently viewed page
    var $cur_page        =  0; // The current page being viewed
    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 == 0 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 + 1 ) . ' to ' ;

            if( ( $curr_offset + $this->per_page ) < ( $this->total_rows -1 ) )
            $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>';
    }
}
// END Pagination Class

Controlador (Posts.php)

El controlador Posts consiste en 3 funciones: __construct(), index() y ajaxPaginationData().

  • La función __construct() carga el modelo Post, la librería Ajax_pagination y define el número de registros por página a través de la variable $this->perPage.
  • En la función index() iniciamos la librería para la paginación con una configuración muy básica. También cargamos la vista index y pasamos los datos a dicha vista.
  • La función ajaxPaginationData() es muy parecida a la función index(). Solo que este método únicamente lo llamaremos cuando se haga clic en los enlaces de paginación ajax.
<?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 = 3;
    }
    
    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;
        $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(){
        $page = $this->input->post('page');
        if(!$page){
            $offset = 0;
        }else{
            $offset = $page;
        }
        
        //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;
        $this->ajax_pagination->initialize($config);
        
        //get the posts data
        $data['posts'] = $this->post->getRows(array('start'=>$offset,'limit'=>$this->perPage));
        
        //load the view
        $this->load->view('posts/ajax-pagination-data', $data, false);
    }
}

Modelo (Post.php)

El modelo Post contiene la función getRows(). Esta función extrae la información de la base de datos y la devuelve en base al límite de registros, el cual consultamos gracias a la variable $params.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Post extends CI_Model{

    function getRows($params = array())
    {
        $this->db->select('*');
        $this->db->from('posts');
        $this->db->order_by('created','desc');
        
        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']);
        }
        
        $query = $this->db->get();
        
        return ($query->num_rows() > 0)?$query->result_array():FALSE;
    }

}

Vista (post/)

La carpeta de vistas post/ contiene dos ficheros: index.php y ajax-pagination-data.php.

index.php

<script src="<?php echo base_url(); ?>assets/js/jquery.min.js"></script>
<div class="container">
    <h1>Ajax Pagination in CodeIgniter Framework</h1>
    <div class="row">
        <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

<?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(); ?>

Fuente: codexworld.com

 

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP