CodeIgniter Ajax form - submitting form

2019-02-19 09:28发布

问题:

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. :)

回答1:

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);
    }
}


回答2:

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.