Geeth Welagedara Geeth Welagedara - 4 months ago 10
Ajax Question

How to display data from code igniter model with AJAX request

My

Codeigniter
site has side panel and when i click or select any options in side panel appropriate content will appear to the main panel.

Home page
URL
is
http://localhost/main/userinfo/allusers

When i click female button
URL
is
http://localhost/main/userinfo/female


enter image description here
i have following output when i made the Ajax request. Where i did the mistake?
enter image description here

Controller(main.php)

class Main extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->model('userinfo_model');
}
public function index() {}
public function userinfo($gender) {
$this->load->view('home/inc/header_view');
$usermain_data['user_info'] = $this->userinfo_model->get_data($gender);
$this->load->view('home/main_view', $usermain_data);
}


Model(userinfo_model.php)

class Userinfo_model extends CI_Model {
function __construct() {
// Call the Model constructor
parent::__construct();
}
function get_data($gender) {
$this->db->select('*');
if($gender == 'female'){
$this->db->where('gender', 0);
}
elseif($gender == 'male'){
$this->db->where('gender', 1);
}
elseif($gender == 'allusers'){
$gNames = array(0, 1);
$this->db->where_in('gender', $gNames);
}
else {
redirect(base_url() . 'main/userinfo/allusers');
}
$query = $this->db->get('tble_userinfo');
//return $query->result();
echo(json_encode($query->result()));
}}


View(main_view.php)

<div class="container">
<div class="row">
<div class="col-md-3 side_menu">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-default gender-label" id="lbl-female" onclick="displayfemale()">
<input type="radio" name="options" id="option1" autocomplete="off">
<span>Female</span>
</label>
<label class="btn btn-default gender-label" id="lbl-male" onclick="displaymale()">
<input type="radio" name="options" id="option2" autocomplete="off">
<span>Male</span>
</label>
</div> <br> <br>
<label class="label nav-label">Age</label>
<select class="btn nav-age-select" id="ageSelect1" autocomplete="off">
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21" selected="selected">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>

</select>
<label class="label nav-label label-to">To</label>
<select class="btn nav-age-select" id="ageSelect2" autocomplete="off">
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25" selected="selected">25</option>
</select>

</div>
<div class="col-md-8 main-body">
<div id="userdata">
<?php
//foreach ($user_info as $info) {
//confuse of adding date here with ajax
//echo $info->content . '<br />' . $info->added_date .'<br />';
//}
?>
</div>
</div>
</div>




<script type="text/javascript">
$(document).ready(function () {
var ajaxUrl = '<?php echo base_url(); ?>' + 'main/userinfo';
var gender = 'allusers'; // defual 1 for female and male both together

getAjax(ajaxUrl, gender);

$("#lbl-female").click(function () {
gender = 'female';
getAjax(ajaxUrl, gender);
});
$("#lbl-male").click(function () {
gender = 'male';
getAjax(ajaxUrl, gender);
});
});
function getAjax(ajaxUrl, gender){
ajaxUrl = ajaxUrl + '/' + gender;
$.ajax({
url: ajaxUrl,
dataType: "JSON",
type: "POST",
success: function (retdata) {
$("#userdata").html('');
if(retdata.hasOwnProperty("error")){
$("#userdata").html('<div">' + retdata.msg + '</div>');
}
else{
$.each(retdata, function(i){
$("#userdata").append(retdata[i].content + '<br>');
});
}

}
});
}



Answer

This answer will have main load both genders initially. Rather than use several gender specific URLs the gender buttons will return the html of the selected gender and dynamically change the html of the page.

main_view.php (with Javascript included)

<div class="container">  
  <div class="row">
    <div class="col-md-3 side_menu">
      <div class="btn-group" data-toggle="buttons">
        <label class="btn btn-default gender-label" id="lbl-female">
          <input type="radio" name="options" id="option1" autocomplete="off">
          <span>Female</span>
        </label>
        <label class="btn btn-default gender-label" id="lbl-male">
          <input type="radio" name="options" id="option2" autocomplete="off">
          <span>Male</span>
        </label>
      </div> <br> <br> 
      <label class="label nav-label">Age</label>
      <select class="btn nav-age-select" id="ageSelect1" autocomplete="off">
        <option value="18">18</option>
        <option value="19">19</option>
        <option value="20">20</option>       
        <option value="21"  selected="selected">21</option>
        <option value="22">22</option>
        <option value="23">23</option>       
        <option value="24">24</option>
        <option value="25">25</option>

      </select>
      <label class="label nav-label label-to">To</label>
      <select class="btn nav-age-select" id="ageSelect2" autocomplete="off">
        <option value="18">18</option>
        <option value="19">19</option>
        <option value="20">20</option>       
        <option value="21">21</option>
        <option value="22">22</option>
        <option value="23">23</option>       
        <option value="24">24</option>
        <option value="25" selected="selected">25</option>
      </select>
    </div>
    <div class="col-md-8 main-body">
      <div id="userdata">
        <?php
        foreach($user_info as $info)
        {
          echo $info->content.'<br />'.$info->added_date.'<br />';
        }
        ?>
      </div>         
    </div>
  </div>
</div>
<script>
  $(document).ready(function () {
  var ajaxUrl = '<?php echo base_url(); ?>' + 'main/userinfo';

  $("#lbl-female").click(function () {
    getAjax(ajaxUrl, 'female');
  });
  $("#lbl-male").click(function () {
    getAjax(ajaxUrl, 'male');
  });
});
function getAjax(URL, gender) {
  $.ajax({
    url: URL,
    data: {gender: gender},
    dataType: "html",
    type: "POST",
    success: function (retdata) {
      $("#userdata").html(retdata);
    }
  });
}
</script>

Note that in the $.ajax options with the line

data: {gender: gender},

we are "posting" data to the controller which will be retrieved by using $this->input->post("gender"); in the AJAX response function.

Models should not do anything but return data for a controller to use. It is the controller's job to determine what happens based on the data returned. So the redirect() call has been removed.

Userinfo_model.php

class Userinfo_model extends CI_Model
{
  function __construct()
  {
    // Call the Model constructor
    parent::__construct();
  }

  // Note the default value for argument $gender. 
  // This means you do not have to pass an argument.
  // If you don't pass one, then !empty($gender) === FALSE
  function get_data($gender = NULL)
  {
    $this->db->select('*');

    //select based on gender. 
    //If no $gender then a "where" clause is not needed and both genders are selected
    if(!empty($gender)) 
    //an argument was provided
    {
      if($gender == 'female')
      {
        $this->db->where('gender', 0);
      }
      else
      {
        $this->db->where('gender', 1);
      }
    }

    $query = $this->db->get('tble_userinfo');
    return $query->result();
  }
}

Finally, we get to the controller. index() will display both genders by calling get_data() without passing an argument to the model. After that the AJAX responder userinfo() will return html of the desired gender to the ajax success function. The success function will replace the existing html with the new html echoed from userinfo().

class Main extends CI_Controller
{
  public function __construct()
  {
    parent::__construct();
    $this->load->model('userinfo_model');
  }

  public function index()
  {
    $usermain_data['user_info'] = $this->userinfo_model->get_data();
    $this->load
        ->view('home/inc/header_view')
        ->view('home/main_view', $usermain_data);
  }

  //Only used to respond to an AJAX request
  public function userinfo()
  {
    $gender = $this->input->post('gender');

    if(empty($gender))
    {
      $out =  "No Users Found";
    }
    else
    {
      $user_info = $this->userinfo_model->get_data($gender);
      $out = "";

      foreach($user_info as $info)
      {
        $out .= $info->content.'<br />'.$info->added_date.'<br />';
      }
    }
    echo $out;
  }

}

This seems reasonably secure so far. The only user input is the gender value. (Never trust user input) Should someone try to pass a value other than the string "female" the database will return only the males info. No user input is presented directly to the database so I don't see any vulnerabilities.