Welcome Guest, Not a member yet? Register   Sign In
Probably something simple...Form repopulation
#1

[eluser]Militis[/eluser]
Hi all. First time posting here, but I've been using Codeigniter for a little while.

I'm in the midst of developing an application for a family member, and have come across a stumbling block. In attempting to setup the ability to edit information in a database, I can't seem to get the form to repopulate if there are errors (or even if the form has been submitted). It could be that I'm not 100% done coding the actual database update, and I haven't set validation rules yet, but I don't think so. I think I missed something, probably even something pretty simple. So far as I can tell though, it should be working the way I want it.

View:
Code:
<?php
        //BOF Edit
        echo '<div id="edit">';
            $query = $this->db->get_where('table', array('id' => $this->uri->segment(3))); //URI: baseurl/index.php/app/edit/$id
            $array = $query->result_array();
    if ($this->input->post('edit')) {
            echo '&lt;form action="' . site_url('/app/edit/' . $this-&gt;uri->segment(3) . '') . '" method="post">';
                echo '<fieldset>';
                echo '<legend>Edit</legend>';
                echo '<label for="field0">Field 0</label>';
                echo '&lt;input type="text" id="field0" name="field0" value="' . htmlspecialchars($this-&gt;session->flashdata('field0')) . '" /><br />';
                echo '<label for="field1">Field 1</label>';
                echo '&lt;input type="text" id="field1" name="field1" value="' . htmlspecialchars($this-&gt;session->flashdata('field1')) . '" /><br />';
                echo '<label for="field2">Field 2</label>';
                echo '&lt;input type="text" id="field2" name="field2" value="' . htmlspecialchars($this-&gt;session->flashdata('field2')) . '" /><br />';
                echo '<label for="notes">Notes</label>';
                echo '&lt;textarea id="notes" name="notes" rows="5" cols="30"&gt;' . htmlspecialchars($this->session->flashdata('notes')) . '&lt;/textarea&gt;&lt;br />';
                echo '<label for="buttons"></label>';
                echo '&lt;input type="submit" id="edit" name="edit" value="Edit" /&gt;';
                echo '&lt;input type="reset" id="reset" name="reset" value="Clear" style="margin-left: 55px;" /&gt;';
                echo '</fieldset>';
            echo '&lt;/form&gt;';
    } else {
            echo '&lt;form action="' . site_url('/app/edit/' . $this-&gt;uri->segment(3) . '') . '" method="post">';
                echo '<fieldset>';
                echo '<legend>Edit</legend>';
                echo '<label for="field0">Field 0</label>';
                echo '&lt;input type="text" id="field0" name="field0" value="' . $array['0']['field0'] . '" /&gt;&lt;br />';
                echo '<label for="field1">Field 1</label>';
                echo '&lt;input type="text" id="field1" name="field1" value="' . $array['0']['field1'] . '" /&gt;&lt;br />';
                echo '<label for="field2">Field 2</label>';
                echo '&lt;input type="text" id="field2" name="field2" value="' . $array['0']['field2'] . '" /&gt;&lt;br />';
                echo '<label for="notes">Notes</label>';
                echo '&lt;textarea id="notes" name="notes" rows="5" cols="30"&gt;' . $array['0']['notes'] . '&lt;/textarea&gt;&lt;br />';
                echo '<label for="buttons"></label>';
                echo '&lt;input type="submit" id="edit" name="edit" value="Edit" /&gt;';
                echo '&lt;input type="reset" id="reset" name="reset" value="Clear" style="margin-left: 55px;" /&gt;';
                echo '</fieldset>';
            echo '&lt;/form&gt;';
    }
            echo '<p><a href="' . site_url('/app/') . '">Back</a></p>';
//            echo '<hr />';
        echo '</div>';
        //EOF Edit

Controller:
Code:
function edit($id)
    {
        // Convert session flashdata messages to Message library compatibility.
        if($this->session->flashdata('error')) {
            $this->messages->add($this->session->flashdata('error_text'), 'error');

        } elseif($this->session->flashdata('warning')) {
            $this->messages->add($this->session->flashdata('warning_text'), 'warning');
        } elseif($this->session->flashdata('success')) {
            $this->messages->add($this->session->flashdata('success_text'), 'success');

        } elseif($this->session->flashdata('message')) {
            $this->messages->add($this->session->flashdata('message_text'), 'message');
        }

        if($this->session->userdata('logged_in') && !$this->input->post('edit'))
        {
            $this->load->view('app/edit');
            $this->session->set_flashdata($_POST);
        } elseif ($this->session->userdata('logged_in') && $this->input->post('edit')) { //Form has been submitted.
            $query = $this->db->get_where('table', array('id' => $id));

            $aa = $query->result_array();
            $flashdata = array('message' => true, 'message_text' => 'If I were working, you could edit field number ' . $aa['0']['field0'] . '.');
//Instead of doing some database work. This will be replaced with the proper model functions.
            $this->session->set_flashdata($flashdata);
            $this->session->set_flashdata($_POST);
            redirect('/app/edit/' . $id . '');
        }
    }

I'm hoping the problem is that I haven't done any of the field validation stuff yet, but I'm pretty sure I shouldn't have to do any actual database work for this to repopulate, even on submit with no validation errors.

Thanks in advance.
#2

[eluser]Militis[/eluser]
And since I hit the character limit on my first message, here's a (simple) map of what SHOULD happen.

Form is populated from database -> changes are made -> form is submitted -> (validation is run) -> data is passed through model to run database functions.

Since I don't want to do the database stuff until I've got the rest of the form working, I've set up a simple message to be displayed in place of the database functions being run. The form SHOULD be repopulated with the edits done, but it isn't. It's like it pulls in data from the database instead.

Again, thanks in advance. Sorry for double posting. I wanted to include this in the original message, but ran out of room.
#3

[eluser]pistolPete[/eluser]
First, you are not following the MVC approach, you should not put database logic in you view!

Why are you trying to reinvent the wheel?
There is already a CI library which handles form validation:
http://ellislab.com/codeigniter/user-gui...ation.html
#4

[eluser]TheFuzzy0ne[/eluser]
Welcome to the CodeIgniter community.

I agree. Using the CodeIgniter form validation library will be beneficial to you. You can then use set_value() to populate the form.
#5

[eluser]Militis[/eluser]
I am going to use the form validation library, I just haven't gotten there yet.

As for MVC, I'm still getting used to OOP, so you'll have to forgive me while I learn. The actual CRUD operations are in the model, but I had the get operations in the view.

So instead of using the session flashdata, I should use set_value() to repopulate?

Thanks for the replies.
#6

[eluser]bEz[/eluser]
@Militis
What I am getting from the replies is that support for the form code you presented would be futile to the goal of MVC and the CI framework.

Also note, other users (like myself) are also reading these post.
So to receive a "temporary" resolution to your issue that will require you to eventually code to the conventions of MVC as suggested, would confuse the other users trying to accomplish this level of learning CI.

I do applaud you for posting, as many early learners take up to 6months to post for assistance. And quite a handful of these guys do take time away from their projects to assist rather well.

Good Luck and look forward to following this thread!

-bEz
#7

[eluser]TheFuzzy0ne[/eluser]
One more thing I'd like to point out, is that flashdata can store an array. Rather than having all of the logic that you have to check for one message type, and then another, and then another etc... I store an array like this:
Code:
$data = array(
        'type' => 'warning',
        'content' => 'This is a warning!'
    );
$this->session->set_flashdata('message', $data);

I then pass it into my view as 'message' (no checking necessary, if it's not set, the function returns FALSE), and I just include a view within my main template, which checks to see if $message is not FALSE. If it's not, FALSE, it print's out the appropriate message. Here's my view. It's included directly inside another view:
Code:
&lt;?php if (! empty($message) && is_array($message)): ?&gt;
        <div class="&lt;?=$message['type']?&gt;">
            <ul>&lt;?php foreach ($message['content'] as $line): ?&gt;

                <li>&lt;?=$line?&gt;</li>
            &lt;?php endforeach; ?&gt;</ul>
        </div>
&lt;?php endif; ?&gt;

I actually use a helper to build the initial array as it's an eye sore building it each time, I just used the array to demonstrate.

Here's my helper function:
Code:
function flash_message($type="", $messages=array())
{
    if (! is_array($messages))
    {
        $messages = array($messages);
    }
    
    $data = array(
        'type' => $type,
        'content' => $messages
    );
    $CI =& get_instance();
    $CI->session->set_flashdata('message', $data));
}

Hopefully this might help you and save you some typing. It's certainly made things easier for me. All I have to do is:
Set the flashdata on the first request (make sure the helper is loaded first!):
Code:
flash_message('ok', 'Entry added successfully added to the database');

Then on the receiving request, pass it to the view:
Code:
$data['message'] = $this->session->flashdata('message');

And include my message.php view from within the view I'm calling.
Code:
$this->load->view('message');

And everything takes care of itself. So now I can pass warnings, confirmations, errors or anything else, and I only have to type three lines of code for the whole thing! Easy, huh? You just need to remember that my message view as is will probably look quite rotten. You'll need to style it with some CSS to make it look CI-exy. Big Grin

Many people will disagree with this, as you shouldn't really use $this in a view, but it works well for me, and would be easy enough to implement without using $this in the view (via another helper), but I think it's overkill.

Hope this helps.
#8

[eluser]Militis[/eluser]
Sorry, I actually forgot about this thread for a bit. I 'finished' the app about a week ago, and it works pretty good. I'll do some tweaks here and there as I continue to learn about CI and OOP.

I still can't get the form to repopulate, and I'm not sure why. But I did finally get things into MVC format, so here they are:

Controller
Code:
function add()
    {
        // Convert session flashdata messages to Message library compatibility.
        if($this->session->flashdata('error')) {
            $this->messages->add($this->session->flashdata('error_text'), 'error');

        } elseif($this->session->flashdata('warning')) {
            $this->messages->add($this->session->flashdata('warning_text'), 'warning');
        } elseif($this->session->flashdata('success')) {
            $this->messages->add($this->session->flashdata('success_text'), 'success');

        } elseif($this->session->flashdata('message')) {
            $this->messages->add($this->session->flashdata('message_text'), 'message');
        }

        $header_data['title'] = 'Imagefitters Art Production Tracking System';
        $header_data['ajaxtype'] = 'add';
        $this->load->view('art/header', $header_data);
        $this->load->view('art/add');
        $companyname = '<a href="http://www.emodicus.com/" target="_blank">emodicus.com</a>';
        $footer_data['copyright'] = $this->art->writecopyright($companyname, TRUE, '2009');
        $this->load->view('art/footer', $footer_data);

    }

    function do_add()
    {

        $rules = array(
                    array(
                        'field' => 'order_num',
                        'label' => 'Order #',
                        'rules' => 'required'
                    ),
                    array(
                        'field' => 'customer',
                        'label' => 'Customer',
                        'rules' => 'required'
                    ),
                    array(
                        'field' => 'num_designs',
                        'label' => '# of Designs',
                        'rules' => 'required'
                    ),
                    array(
                        'field' => 'receive',
                        'label' => 'Receive Date',
                        'rules' => 'required'
                    ),
                    array(
                        'field' => 'due',
                        'label' => 'Due Date',
                        'rules' => 'required'
                    )
                );


        $this->form_validation->set_rules($rules);
        $this->form_validation->set_error_delimiters('', '');

        if($this->session->userdata('logged_in')) {
            if ($this->form_validation->run() == false) {

                $flashdata = array('error' => true, 'error_text' => $this->form_validation->error_string('','<br />'));

                $this->session->set_flashdata($flashdata);

                $this->session->set_flashdata($_POST);

                redirect('/art/add/');

            } else {
                $this->art->add($_POST);
            }
        }

    }

Re: Flashdata, I know it can, and I've quit using it except for status messages, which I then convert to the Message library (IIRC, it's in the Wiki) for easy posting.

The View is going to have to be posted seperately...it's telling me the maximum number of allowed characters is 6000, but told me I had 10,000 below the message box...-.-
#9

[eluser]Militis[/eluser]
And the View, since I had to split things up.

View
Code:
//BOF Add art
        echo '<div id="artadd">';
            echo '&lt;form action="' . site_url('/art/do_add/') . '" method="post"&gt;';
                echo '<fieldset>';
                echo '<legend>Add</legend>';

                echo '<label for="order_num">Order #:</label>';

                echo '&lt;input type="text" id="order_num" name="order_num" value="' . set_value('order_num') . '" /&gt;&lt;br />';

                echo '<label for="customer">Customer:</label>';

                echo '&lt;input type="text" id="customer" name="customer" value="' . set_value('customer') . '" /&gt;&lt;br />';
                echo '<div id="customer_autocomplete_choices" class="autocomplete"></div>';
                echo '<label for="num_designs"># of Designs:</label>';
                echo '&lt;input type="text" id="num_designs" name="num_designs" value="' . set_value('num_designs') . '" /&gt;&lt;br />';
                echo '<label for="receive">Receive Date:</label>';
                echo '&lt;input type="text" id="receive" name="receive" value="' . set_value('receive', '0000-00-00') . '" class="calendarSelectDate" /&gt;&lt;br />';
                echo '<label for="due">Due Date:</label>';
                echo '&lt;input type="text" id="due" name="due" value="' . set_value('due', '0000-00-00') . '" class="calendarSelectDate" /&gt;';
                echo '&lt;input type="radio" name="priority" value="1"' . set_radio('priority', '1') . ' /&gt; <abbr title="Rush" class="priority_1">1</abbr> &lt;input type="radio" name="priority" value="2"' . set_radio('priority', '2') . ' /&gt; <abbr title="Current" class="priority_2">2</abbr> &lt;input type="radio" name="priority" value="3"' . set_radio('priority', '3') . ' /&gt; <abbr title="Pending" class="priority_3">3</abbr>';
                echo '<br />';
                echo '<label for="notes">Notes:</label>';
                echo '&lt;textarea id="notes" name="notes" rows="5" cols="30"&gt;' . set_value('notes') . '&lt;/textarea&gt;&lt;br />';
                echo '<label for="button"></label>';

                echo '&lt;input type="submit" id="add" name="add" value="Add" /&gt;';
                echo '</fieldset>';
            echo '&lt;/form&gt;';
            echo '<div id="calendarDiv"></div>';
            echo '<p><a href="' . site_url('/art/') . '">Home</a></p>';

//            echo '<hr />';
        echo '</div>';

        //EOF Add art

If it's needed, I'll post the model, but I think the problem is somewhere in the Controller/View side of the triangle.

I'm sure I could use the CI form helper to make the form, but I wasn't aware of having to use it with form validation and still prefer doing it by hand (I'm sure that'll change as I get more used to the CI-way). I could also probably use here document syntax to echo, instead of using echo over and over, but I'm unaware of any huge performance losses or gains either way.

Edit: Ah! Here's the Messages library.

http://codeigniter.com/wiki/Messages/
#10

[eluser]TheFuzzy0ne[/eluser]
You need to display the view in the same controller that did the validation, as that's what the form validation library expects. The form validation library draws it's values from the POST array, which no longer exists after the redirect (and passing it over as a flash variable is not the way to do things).

You can put the validation in a standalone function, and call it from the function you're submitting to, no problem, but as soon as you redirect, it's game over. Generally, you should only redirect once the form validation has passed and you've done the database insert/update.




Theme © iAndrew 2016 - Forum software by © MyBB