I'm currently in the process of rewriting an entire site of mine so that it's compatible with CI. I'm fairly new with CI and the MVC pattern in general. I followed this tutorial and have made a pretty decent template for the view part of the MVC pattern. The thing is, a lot of my site uses jQuery/AJAX to make it more dynamic. For example, on all of my pages on my site, I have an input field that uses jQuery to load a PHP file upon keyup.
<script type="text/javascript">
$("#search_bar").keyup(function(){
var search = $("#search_bar").val();
var url = "search_bar.php";
var data = "q="+ search;
$('#livesearch').load(url, data);
$("#livesearch").slideDown("fast");
});
</script>
<input type='text' maxlength='30' id='search_bar' autocomplete='off' placeholder='Browse Teams' />
<div id='livesearch' style='display:none;'></div>
All of the backend work that's required to load the results happens in the PHP file that loaded via jQuery (search_bar.php). So, should "search_bar" be its own View that's triggered by its own Controller and then Modeled by a model called "search_bar"? Again, I'm very new to the MVC pattern and am not quite sure how properly integrate AJAX with a object oriented framework like CI.
Thanks
Directly calling the view in ajax request is not a good practice call the controller which loads the view or directly do the stuff in the controller's function
<script type='text/javascript'>
$('#search_bar').keyup(function(){
$.ajax({
url: 'yourcontrollername/search_bar_yourfunction',
type:'POST',
data: {q: search,
success: function(result){
$("#livesearch").html(result);
$("#livesearch").slideDown("fast");
}
});
});
</script>
Your controller code
class yourcontrollername extends My_Controller {
public function search_bar_yourfunction() {
//do your stuff and store in the $data[] array
$this->load->view("search_bar",$data); //search_bar.php
die();
}
}
}
You should go from your View to the Controller:
<script type='text/javascript' language='javascript'>
$('#search_bar').keyup(function(){
$.ajax({
url: 'search_bar.php',
type:'GET',
data: {q: search,
success: function(result){
//Insert code here
} // End of success function of ajax form
}); // End of ajax call
});
</script>
Then in your controller, load a model if necessary:
public function weigeren() {
$user = $this->CI->authex->getUserInfo();
$data['title'] = "Test";
$this->load->model('search_model');
$query = $this->input->get('q');
if (isset($user)) {
echo $this->search_model->search($query);
}
}
I find one way to load ajax (jquery) in CodeIgniter 3. Example,
structure of folder:
controllers/Upload.php
view/admin/ajax_view/ajax_images.php
controllers/upload:
public function process()
{
$data['my_picture'] = array(
'pic_id' => '1',
'pic_path' => 'http://example.com/images',
);
$this->load->view('admin/ajax_view/ajax_images', $data);
}
view/admin/ajax_view/ajax_images:
<?php foreach($my_picture as $key => $row): ?>
<td><?php echo $my_picture['pic_path']; ?></td>
<?php endforeach; ?>
view/admin/form_upload:
<tbody>
<tr class="trbody">
<th scope="row">1</th>
<!-- <td></td> --> <!--comments this because appends element jquery-->
</tr>
</tbody>
<script type="text/javascript">
$(document).ready(function(){
$('#my_button').click(function(e){
e.preventDefault;
$.ajax({
url: 'upload/process',
dataType: 'text',
type: 'post',
success: function(data){
$('.trbody')
.append(
'<td>'+ data + '</td>'
);
},
error: function(errorThrown){
console.log(errorThrown);
}
});
});
});
</script>
To this way, I separated view of ajax of whole pages and load ajax view when
event trigger.
Related
I am having a view with 2 buttons in my codeigniter view:
<div class="btn-main col-md-3 col-md-offset-3">
<button id="simu-mono" type="button" class="btn btn-default">SIMULATION MONO SITE</button>
</div>
<div class="btn-main col-md-3">
<button id="simu-multi" type="button" class="btn btn-default">SIMULATION MULTI SITE</button>
</div>
I would like to call another a controller to launch then a view when the button is clicked
I tried out to call the controller simu_mono by javascript, putted on /controller/simu_mono.php but doesn' t work
$(document).ready(function(){
$("#simu-mono").click(function(){
type:'GET',
url:'simu_mono'
});
$("#simu-multi").click(function(){
});
});
simu_mono.php:
<?php
class simu_mono extends CI_Controller {
public function index()
{
$this->load->view('simu_mono');
echo 'Hello World!';
}
}
?>
Thanks for your helps
Cheers
Please, if u want to redirect only use following code:
$(document).ready(function(){
$("#simu-mono").click(function(){
window.location = base_url + "/simu_mono";
});
$("#simu-multi").click(function(){
window.location = base_url + "/simu_multi";
});
});
Note that you might need base_url, use this snippet to load base_url in JavaScript variable
<script>
base_url = <?= base_url()?>
</script>
put code above in some kind of view that is loaded always (before any other JavaScript code is executed)
Additional step would be to set up routes that take care of ugly underscore symbol (_)
something like:
routes.php
$route['simu-mono'] = "simu_mono";
$route['simu-multi'] = "simu_multi";
this way you go to your page and controller following way: yourserver.ufo/simu-mono and yourserver.ufo/simu-multi
You're not doing any class of AJAX call within your javascript. I assume you're using jQuery, so, your call should be something like:
$("#simu-mono").click(function(){
$.ajax({
url: "http://your-url.com/controller/method",
type: 'post', // <- Or get option, whatever you prefer
dataType: 'json', // <- This is important to manage the answer in the success function
//data: { param1: "value1", param2: "value2"}, <- You could add here any POST params you wanted
success: function(data){
if (data.view) {
$('#here_view').html(data.view); // <- '#here_view' would be the id of the container
}
if (data.error){
console.log(data.error);
}
}
});
});
This will call your method, where you will have to indicate you want to pass the view:
<?php
class simu_mono extends CI_Controller {
public function index()
{
$return = array(
'view' => $this->load->view('simu_mono')
);
echo json_encode( $return );
}
}
?>
json_encode will allow you easily pass vars and data from PHP to your javascript, and manage them in the client view. As you see in the javascript, I added data.error, this is just in case you'll have more logic, maybe change the view you're sending, send an error if you sent data and want to control them, etc.
Of course, in your javascript you could take the url from the clicked button, and in data.view parat of the success function, you may print in the screen a modal, send the view to a container, whatever you wanted, XD
I finally made my AJAX working in Extbase Typo3 6. However, I'm trying to use the returned array from AJAX in my FLUID view.
my Ajax action in Controller:
public function ajaxAction(){
$id = $this->request->getArgument['id'];
$record = $this->articleRepository->findByUid($id);
return json_encode(['record'=>$record,'status' => 'Loaded']);
}
My AJAX :
function dropCall(selectFieldObj) {
$.ajax({
type: 'POST',
url: link,
dataType: 'json',
success: function(data){
alert(data.status);
}
});
}
Now the question is how do I use the data object sent from the controller action in my View ? The alert is being displayed.
My List.html view
<script type="text/javascript">
var link
= '<f:uri.action action="ajax" controller="Article" pageType="99" arguments="{data:1}"/>';
</script>
<script type="text/javascript" src="fileadmin/myScript.js"></script>
<select id="drop" onchange="dropCall(this)">
<option value="1">Apple</option>
<option value="2">Mango</option>
<option value="3">Grape</option>
</select>
In my view, I should be able to do something like
<h1> {record.name} </h1>
EDIT
The object record might contain many properties and each record.property like record.name will be under <h1> tags and record.somethingelse can be under some under tag.
Just like we send objects from controller to view and use them in FLUID, I would want to do the same with AJAX
I am trying to display different forms based on user type using Ajax post request. The request response works fine but I don't know how to display the form. For example, if the user selects parent then I want the parent form to be displayed and so on. I'm using ZF 1.12.
public function init() {
$contextSwitch = $this->_helper->getHelper('AjaxContext');
$contextSwitch =$this->_helper->contextSwitch();
$contextSwitch->addActionContext('index', 'json')
->setAutoJsonSerialization(false)
->initContext();
}
public function indexAction() {
$this->view->user = $this->_userModel->loadUser($userId);
//if($this->_request->isXmlHttpRequest()) {
//$this->_helper->layout->disableLayout();
//$this->_helper->viewRenderer->setNoRender(true);
if ($this->getRequest()->isPost()){
$type = $_POST['type'];
$this->view->userForm = $this->getUserForm($type)->populate(
$this->view->user
);
}
}
And here's what I have on the client side. What do I need to write in the success section?
<script type="text/javascript">
$(document).ready(function(){
$('#userType').on('change', function(){
var type = $(this).val();
select(type);
});
});
function select(type) {
$.ajax({
type: "POST",
url: "admin/index/",
//Context: document.body,
data: {'type':type},
data: 'format=json',
//dataType: "html",
success: function(data){
// what to do here?
},
error: function(XMLHttpRequest, textStatus, errorThrown) {}
});
}
</script>
<form id="type" name="type" method="post" action="admin/index">
<select name='userType' id='userType' size='30'>
<option>admin</option>
<option>parent</option>
<option>teacher</option>
</select>
</form>
<div id="show">
<?php //echo $this->userForm;?>
</div>
If your ajax request form returns you the HTML from the Zend_Form, you could simply write the HTML in the #show div.
In you view you will need to do this :
echo $this->userForm;
This way, all the required HTML will be written on the server side, before sending the response to the HTML page. In the HTML page you then just have to write the response in the right location with the method $('#show').html(data). You also have to make sure that each of your forms has the right action when you render them.
The other option would be to have all three forms hidden in your page (through Javascript) upon loading and based on the select (Generated with JS), display the right form. This way you don't have to load data from an external source and if someone have JS disabled, he still can use the application. On the other hand, this method will have each page load about 1/2 a KB more of data.
I'm new to stackoverflow and to CodeIgniter and I'm currently experimenting on some simple code examples I have found on the Internet in order to get a start. The one I'm working on right now is a form which uses CI and Ajax (jQuery) along with saving the inputs of the form in a database and then display the most recent of them on the same page as the form.
If I confused you it's the 4.7 application example from here. The initial source code lies here but I have modified it in order to work with the latest release of CI and I quote all my MVC files just below.
Controller:
<?php
class Message extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->helper('form');
$this->load->helper('url');
$this->load->helper('security');
$this->load->model('Message_model');
}
function view()
{
//get data from database
$data['messages'] = $this->Message_model->get();
if ( $this->input->is_ajax_request() ) // load inline view for call from ajax
$this->load->view('messages_list', $data);
else // load the default view
$this->load->view('default', $data);
}
//when we pres the submit button from the form
function add()
{
if ($_POST && $_POST['message'] != NULL)
{
$message['message'] = $this->security->xss_clean($_POST['message']);
$this->Message_model->add($message);
}
else
{
redirect('message/view');
}
}
}
?>
Model:
<?php
class Message_model extends CI_Model
{
function __construct()
{
parent::__construct();
$this->load->database();
}
function add($data)
{
$this->db->insert('messages', $data);
}
function get($limit=5, $offset=0)
{
$this->db->order_by('id', 'DESC');
$this->db->limit($limit, $offset);
return $this->db->get('messages')->result();
}
}
?>
Views
default.php:
<!-- called using message/view -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="<?php echo base_url('js/jquery-1.8.1.min.js'); ?>" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function()
{
$('#submit').click(function(e)
{
e.preventDefault();
var msg = $('#message').val();
$.post("", {message: msg}, function() {
$('#content').load("");
$('#message').val('');
});
});
});
</script>
</head>
<body>
<?php echo form_open("message/add"); ?>
<input type="text" name="message" id="message">
<input type="submit" value="submit" name="submit" id="submit">
<?php echo form_close(); ?>
<div id="content"></div>
</body>
</html>
messages_list.php:
<!-- called from ajax call -->
<ol>
<?php foreach ($messages as $cur): ?>
<li><?php echo $cur->message; ?></li>
<?php endforeach; ?>
</ol>
The problem mainly lies in the 1st of the views (default.php). That is, if I omit the e.preventDefault(); line from the javascript code then the form loads a different page (message/add as the form action parameter implies) which is a blank page, also cancelling the ajax behavior of my application that way.
On the other hand, if I actually add this line then the add method of my message controller isn' t called, thus not adding what I've typed into the database.
Finally, I tried the following js code instead of the other above:
$(document).ready(function()
{
$('#submit').click(function(e)
{
e.preventDefault();
var msg = $('#message').val();
$.post("<?php echo base_url(); ?>message/add", {message: msg}, function() {
$('#content').load("");
$('#message').val('');
});
});
});
but that way it seems as the $.post() crashes because nothing is executed in the function which is supposed to run on a successful post() call.
Any help appreciated and sorry for the big post. :)
You are correct that you must call e.PreventDefault();, but you must also deal with the response from the callback function, which you are not. The callback takes a few arguments but the first one is what you're interested in, it is the response from your server. I've denoted it as r below:
$(document).ready(function(){
$('#submit').click(function(e){
e.preventDefault();
var msg = $('#message').val();
$.post("<?php echo base_url(); ?>message/add", {message: msg}, function(r) {
//do something with r... log it for example.
console.log(r);
});
});
});
I've also removed $.("#content").load(...);. This would actually perform another AJAX request when the first one is complete.
Now, inspecting your controller...please refrain from using $_POST. CodeIgniter provides you with $this->input->post() as part of the Input Library. If you turn on Global XSS filtering in config/config.php you won't have to xss clean it either. You can clean on a post-by-post basis by using $this->input->post('name', true);
I recommend this instead:
function add(){
$m = $this->input->post('message', true);
if($m){
$this->Message_model->add($m);
}
}
The problem doesn't lie with the CI, its the JS that is wrong,
$(document).ready(function()
{
$('#submit').click(function(e)
{
e.preventDefault();
var msg = $('#message').val();
$.post("<?php echo base_url(); ?>message/add", {message: msg}, function() {
$('#content').load("<?php echo base_url(); ?>/message/view");
$('#message').val('');
});
});
});
The e.preventDefault() is used to stop the default behaviour of the submit button (which will take you to message/add), which we don't want. You are correct in adding the URl paramter to the $.post() function later, but in the callback function, the .load loads the URL that is passed to it into the #content, so without passing any url, of course there won't be anything to load.
How make Zend_Form submission without reload a page - with Ajax?
This is code for create form that reload a page when submitted, what should be change or add that this form will submit with ajax (1.regular solution 2.jquery solution):
Form:
class Application_Form_Login extends Zend_Form
{
public function init()
{
$username=new Zend_Form_Element_Text('username');
$username ->addFilter('StringToLower')
->addValidator('alnum');
$password=new Zend_Form_Element_Text('password');
$password->addFilter('StringToLower')
->addValidator('alnum');
$submit=new Zend_Form_Element_Submit('submit');
$this->addElements(array($username,$password,$submit));
}
}
Controller:
$form = new Application_Form_Login();
$request = $this->getRequest();
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
if ($this->_process($form->getValues())) {
//code indside
}
}
}
$this->view->form = $form;
View:
<?
echo $this->form;
?>
My proposal that I don't think is proper(does form make filtering and validation?) for View:
<?
echo $this->form;
?>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('form').submit(function(){
var sendData=$(this).serialize();
$.ajax(
{
url:'',
dataType:'json',
type:'POST',
data:sendData,
success: function(data) {
}
});
return false;
});
});
</script>
Thanks
Well,
for filtering/validation you might want to send the form using Ajax and by knowing at the server-side that it is an Ajax request (you can use a flag for that, like a header, search for knowing if a request is ajax or not) and sending back only the form 'area'. Then when you receive it you can overwrite it.
There is currently no wiser way to do it with Zend_Form I think.