Cannot get FlexiGrid for CodeIgniter to work
I'm trying to use FlexiGrid plugin with CodeIgniter, but when the page displays the grid shows, but there are no records, and there is a little message saying that you should wait while it's processing, which never goes away...
I'm using one of my own databases, so I modified parts of the code to use fields in my database (id, username, email).
Flexigrid controller:
<?php
class Flexigrid extends CI_Controller
{
/* function Flexigrid ()
{
parent::Controller();
$this->load->helper('flexigrid');
}
*/
function __construct()
{
parent::__construct();
$this->load->helper('flexigrid');
}
function index()
{
//ver lib
/*
* 0 - display name
* 1 - width
* 2 - sortable
* 3 - align
* 4 - searchable (2 -> yes and default, 1 -> yes, 0 -> no.)
*/
$colModel['id'] = array('id', 40, TRUE, 'center', 2);
$colModel['username'] = array('username', 40, TRUE, 'center', 0);
$colModel['email'] = array('email', 180, TRUE, 'left', 1);
/*
* Aditional Parameters
*/
$gridParams = array(
'width' => 'auto',
'height' => 400,
'rp' => 15,
'rpOptions' => '[10,15,20,25,40]',
'pagestat' => 'Displaying: {from} to {to} of {total} items.',
'blockOpacity' => 0.5,
'title' => 'Hello',
'showTableToggleBtn' => true
);
/*
* 0 - display name
* 1 - bclass
* 2 - onpress
*/
$buttons[] = array('Delete', 'delete', 'test');
$buttons[] = array('separator');
$buttons[] = array('Select All', 'add', 'test');开发者_StackOverflow社区
$buttons[] = array('DeSelect All', 'delete', 'test');
$buttons[] = array('separator');
//Build js
//View helpers/flexigrid_helper.php for more information about the params on this function
$grid_js = build_grid_js('flex1', site_url("/ajax"), $colModel, 'id', 'asc', $gridParams, $buttons);
$data['js_grid'] = $grid_js;
$data['version'] = "0.36";
$data['download_file'] = "Flexigrid_CI_v0.36.rar";
$this->load->view('flexigrid', $data);
}
function example()
{
$data['version'] = "0.36";
$data['download_file'] = "Flexigrid_CI_v0.36.rar";
$this->load->view('example', $data);
}
}
?>
Flexigrid view (only changes in head to correct paths to css and js):
<head>
<title>Flexigrid Implemented in CodeIgniter</title>
<link href="<?=$this->config->item('base_url');?>assets/flexigrid/css/style.css" rel="stylesheet" type="text/css"/>
<link href="<?=$this->config->item('base_url');?>assets/flexigrid/css/flexigrid.css" rel="stylesheet"
type="text/css"/>
<script type="text/javascript" src="<?=base_url()?>assets/scripts/jquery-1.5.1.min.js"></script>
<script type="text/javascript"
src="<?=$this->config->item('base_url');?>assets/flexigrid/js/jquery.pack.js"></script>
<script type="text/javascript"
src="<?=$this->config->item('base_url');?>assets/flexigrid/js/flexigrid.pack.js"></script>
</head>
ajax_model:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Eye View Design CMS module Ajax Model
*
* PHP version 5
*
* @category CodeIgniter
* @package EVD CMS
* @author Frederico Carvalho
* @copyright 2008 Mentes 100Limites
* @version 0.1
*/
class Ajax_model extends CI_Model
{
/**
* Instanciar o CI
*/
/* public function Ajax_model()
{
parent::Model();
$this->CI =& get_instance();
}*/
function __construct()
{
parent::__construct();
$this->CI =& get_instance();
}
public function get_countries()
{
//Select table name
$table_name = "users";
//Build contents query
$this->db->select('id,username,email')->from($table_name);
$this->CI->flexigrid->build_query();
//Get contents
$return['records'] = $this->db->get();
//Build count query
$this->db->select('count(id) as record_count')->from($table_name);
$this->CI->flexigrid->build_query(FALSE);
$record_count = $this->db->get();
$row = $record_count->row();
//Get Record Count
$return['record_count'] = $row->record_count;
//Return all
return $return;
}
/**
* Remove country
* @param int country id
* @return boolean
*/
public function delete_country($country_id)
{
$delete_country = $this->db->query('DELETE FROM country WHERE id=' . $country_id);
return TRUE;
}
}
?>
Ajax controller (had to use the non-JSon extension code, so the other part is commented out, according to the instructions on the FlexiGrid web site. Also, I was a bit puzzled when modifying the $recorde_item array, because the example had id twice at the beginning. I thought this must be a mistake, but tried adding a second id row too, didn't help either):
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Ajax extends CI_Controller
{
/* function Ajax ()
{
parent::Controller();
$this->load->model('ajax_model');
$this->load->library('flexigrid');
}*/
function __construct()
{
parent::__construct();
$this->load->model('ajax_model');
$this->load->library('flexigrid');
}
function index()
{
//List of all fields that can be sortable. This is Optional.
//This prevents that a user sorts by a column that we dont want him to access, or that doesnt exist, preventing errors.
$valid_fields = array('id', 'username', 'email');
$this->flexigrid->validate_post('id', 'asc', $valid_fields);
//Get "countries"
$records = $this->ajax_model->get_countries();
//Init json build
if ($this->flexigrid->init_json_build($records['record_count'])) {
//Add records
foreach ($records['records']->result() as $row)
{
$record_item = array($row->id,
$row->username,
$row->email
);
$this->flexigrid->json_add_item($record_item);
}
//Last item added, close up.
$this->flexigrid->json_add_item();
}
//Print please
$this->output->set_header($this->config->item('json_header'));
$this->output->set_output($this->flexigrid->json_build);
/*$this->output->set_header($this->config->item('json_header'));*/
/*
* Json build WITH json_encode. If you do not have this function please read
* http://flexigrid.eyeviewdesign.com/index.php/flexigrid/example#s3 to know how to use the alternative
*/
/* foreach ($records['records']->result() as $row)
{
$record_items[] = array($row->id,
$row->id,
$row->iso,
$row->name,
'<span style=\'color:#ff4400\'>' . addslashes($row->printable_name) . '</span>',
$row->iso3,
$row->numcode,
'<a href=\'#\'><img border=\'0\' src=\'' . $this->config->item('base_url') . 'public/images/close.png\'></a> '
);
}
//Print please
$this->output->set_output($this->flexigrid->json_build($records['record_count'], $record_items));*/
}
//Delete Country
function deletec()
{
$countries_ids_post_array = split(",", $this->input->post('items'));
foreach ($countries_ids_post_array as $index => $country_id)
if (is_numeric($country_id) && $country_id > 1)
$this->ajax_model->delete_country($country_id);
$error = "Selected countries (id's: " . $this->input->post('items') . ") deleted with success";
$this->output->set_header($this->config->item('ajax_header'));
$this->output->set_output($error);
}
}
?>
Well, that should be it. I also had to change the "extends Controller" etc to "extends CI_Controller" since the code in the example seems to be for an older version of CodeIgniter.
But again, it doesn't work. I only get an empty grid. The database table does definitely have the fields I mentioned. I can't find any typos myself at least. It's also my default database in CodeIgniter, and I have no trouble connecting to it in other cases. And it is autoloaded, so I'm guessing that should work automatically, right? I shouldn't have to connect to the database manually here, since it uses the $db variable...
Any ideas then why it isn't working?
I Implemented Flexigrid with Codeigniter 2.1.0. You can download the code from my blog. Flexigrid in Codeigniter 2.1.0 and you can check the tutorial at Flexigrid Tutorial
Not sure if you still need this help or not, and i'm not sure i'm the best to teach as i'm still new to PHP and don't know the most "secure" practices, however, the following is what I was able to do with flexgrid and may help future users, or spark a more "secure" idea from a more advanced user. Without further adieu, my solution:
In the javasript grabbing the and using the json is EASY, check it: keep in mind i tried to keep this very generic & removed all possible personal values ... it think
var flexset = {
url: 'https://www.yourSite.com/index.php/yourController/yourDBFunc',
dataType: 'json',
colModel : [
{display: 'A Column', name: 'a_col', width: 80, sortable: true, align: 'center'}, // where name=the name of the column in the database
{display: 'Another Column', name: 'another_col', width: 110, sortable: false, align: 'center'}
],
buttons : [ {name: "aButton", onpress: someFunction} ],
searchitems : [
{display: 'A Column (some more info if you want)', name: 'a_col', isdefault: true}, // where name=the name of the column in the database
{display: 'Quantity', name: 'charge'}
],
sortname: "a_col", // the name of the column in the database
sortorder: "desc", // desc or asc
usepager: true,
title: 'Some grid title',
useRp: true,
rp: 20,
showTableToggleBtn: true,
resizable: true,
width: "100%",
height: "400px",
singleSelect: true,
onSuccess: function() {
// do some work each time grid is loaded/refreshed, for instance, manipulate certain cells to have specific bgcolor based on content
console.log('onSuccess:\t\t', this, gridData);
console.log('Your inner table:\t', gridData.bDiv);
// you can get specific cells by searching from an attribute called "abbr" on each cell,
// it will = the same "name" you used when setting up the column that cell belongs too
console.log($(gridData.bDiv).find("td[abbr=transactionType]"));
}
}
$("#yourGrid").flexigrid(flexset);
In php, it gets a little harder as i use 2 functions, one public and one private. The private one actually makes the DB query while the public one is accessed by flexigrid to get the resulting data as json_encoded.
The Public Function
public function getJSONData() {
// to ensure its being pulled from a logged user,
// i always set at least one "where" var by hand,
// in this case, i am going to set the where to
// look for all rows containing this user's id,
// so i quickly grab the session var for the current id
$userID = $this->session->userdata('userID');
// should easily be greater than false in this case unless maybe it's id is 0?
// in any case, this is not the exact var i check, but same exact concept and my stuff works
if ($userID) {
// Return JSON data
$data = array();
// first i check post for a page number and go ahead and set the page
// this will be usful later in setting up the page query
$data['page'] = floatval(($this->input->post('page', TRUE))) ? floatval($this->input->post('page', TRUE)) : 1;
$value = array(
'select' => '*',
'where' => array( 'ownerID' => $userID ), // here you see my preset where clause, not absolutly necesary but useful, with some slight manipulation, you could easily redo this how you like
'orderBy' => array( 'a_col' => 'desc' ) // here i set a default orderby in case it's not provided by the post
);
// Get all other POSSIBLE posted data and save it to $value for passing to private func
if ($this->input->post('qtype', TRUE) && $this->input->post('query', TRUE)) $value['where'][$this->input->post('qtype', TRUE)] = $this->input->post('query', TRUE);
if ($this->input->post('sortname', TRUE) && $this->input->post('sortorder', TRUE)) $value['orderBy'] = array( $this->input->post('sortname', TRUE) => $this->input->post('sortorder', TRUE) );
if ($this->input->post('rp', TRUE)) $value['limit'] = array( $this->input->post('rp', TRUE) => (($data['page'] - 1) * floatval($this->input->post('rp', TRUE))) );
// call private function to get the desired data from db
$results = $this->getDBData($value);
// set return data's total count
$data['total'] = $results["total"]["absolute"];
// now we clearly define our "ROWS" for the return data to display in our final grid output
$data['rows'] = array();
foreach($results["rows"] as $k => $v) {
$data['rows'][] = array(
"id" => $v["id"],
"cell" => array( // keep in mind the order of these result here need match the order of the cols you set in the flexset options
$v["a_col"],
$v["another_col"]
)
);
};
// finally, json encode the data to be returned
$data = json_encode($data);
echo($data); // and echo the data to our ajax caller
};
}
The Private Funtion should be pretty self-explanitory
private function getDBData($val) {
$data = array( 'options'=>array(), 'rows'=>array(), 'total'=>array( 'absolute'=>0, 'offset'=>0 ) );
if (array_key_exists("from", $val)) {
$select = (array_key_exists("select", $val)) ? $val["select"] : "*";
$from = $val["from"]; // cannot be changed
$where = array(); // (col => value)
$orderBy = array(); // (name => direction)
$limit = array(); // "totalLimit" or (start => offset)
$limitType = "array";
$total = 0;
if (array_key_exists("where", $val)) if (gettype($val["where"]) === "array") $where = $val["where"];
if (array_key_exists("orderBy", $val)) if (gettype($val["orderBy"]) === "array") $orderBy = $val["orderBy"];
if (array_key_exists("limit", $val)) {
if (gettype($val["limit"]) === "array" || gettype($val["limit"]) === "integer" || gettype($val["limit"]) === "string") {
$limit = $val["limit"];
$limitType = gettype($val["limit"]);
};
};
$options = array( 'select'=>$select, 'from'=>$from, 'where'=>$where, 'orderBy'=>$orderBy, 'limit'=>$limit, 'limitType'=>$limitType );
$this->db->select($select);
$this->db->from($from);
if (count($where) > 0) $this->db->where($where);
if (count($orderBy) > 0) {
foreach ($orderBy as $k => $v) {
$this->db->order_by($k, $v);
};
};
if (gettype($limit) === "array") {
foreach ($limit as $k => $v) {
$this->db->limit($k, $v);
};
}
elseif (gettype($limit) === "integer" || gettype($limit) === "string") {
$this->db->limit($limit);
};
$records = $this->db->get();
$results = $records->result_array();
if (count($where) > 0) {
$total = $this->db->get_where($from, $where)->num_rows;
}
else {
$total = $this->db->get($from)->num_rows;
};
$data["options"] = $options;
$data["rows"] = $results;
$data["total"]["absolute"] = $total;
$data["total"]["offset"] = $records->num_rows;
};
return($data);
}
精彩评论