Welcome Guest, Not a member yet? Register   Sign In
JQuery with forms help needed
#1

[eluser]gigas10[/eluser]
Hi there,
Let me start off saying I'm using MSSQL and IIS 6.0... Not that I had a choice. Anyhow, I have a problem with JQuery and a form, I'm using jquery so people can add another element to the field, from 0-N. It works dandy and what not, however, when you submit the form, if errors are found and it posts you back to the form with the errors. It fills in the fields, but the fields the user added are gone. I don't know how to keep the stuff the submitted through those fields they dynamically added via jquery. I tried foreaching with the set_value('field_name[]'), however it tells me invalid argument supplied for foreach. The information inside the append works fine, when you click add it shows a select box with the appropriate data supplied.

Here is my code.

Code:
[removed]
function addRootCause() {
    var id = document.getElementById("id").value;
    $("#root-cause").append("<p id='row" + id + "'><select name=\"root_cause[]\">&lt;
?php foreach($root_causes AS $rc) { ?&gt;<option value=\"&lt;?=$rc->id;?&gt;\"&lt;
?php if(validation_errors()) { if($rc->id==set_value('root_cause'))
{ echo " SELECTED"; } } ?&gt;>&lt;?=$rc->cause;?&gt;</option>&lt;?php } ?&gt;</select>&nbsp;&nbsp;<a href='#'>Remove</a><p>");


    $('#row' + id).highlightFade({speed:1500});

    id = (id - 1) + 2;
    document.getElementById("id").value = id;
}

function removeFormField(id) {
    $(id).remove();
}
[removed]
&lt;a href="?/main/index/">Home&lt;/a> > New Record
        &lt;?php
        if(validation_errors()) {
            echo validation_errors();
        }
        ?&gt;

               &lt;?=form_open("main/newrecord/"); ?&gt;
               <p>
               <div id="edit-record-title">New Record</div>
               <hr class="main"/>
               <div id="record-lines">
                   <strong>Root Cause</strong>:
                   <select name="root_cause[]">
                   &lt;?php
                   foreach($root_causes AS $rc) {
                       ?&gt;<option value="&lt;?=$rc->id;?&gt;"&lt;?php if(validation_errors()) { if($rc->id==set_value('root_cause[]')) { echo " SELECTED"; } } ?&gt;>&lt;?=$rc->cause;?&gt;</option>&lt;?php
                   } ?&gt;
                   </select>
                   &lt;input type="hidden" id="id" value="1"&gt;
                   &lt;a href="#"&gt;Add&lt;/a&gt;
<div id="root-cause"></div&gt;
               &lt;/div&gt;
              &lt;/p>
                &lt;center&gt;
                    &lt;input type="submit" value="Add Record" name="submit"&gt;
                &lt;/center&gt;
                &lt;/form&gt;
#2

[eluser]slowgary[/eluser]
I found your description and code difficult to read. Have you copied and pasted your code from word? It has the non-standard double quote characters. You're a microsoft junkie, I can tell. Smile

Anyways... it seems like what you're saying is that your form allows a user to "add a field", but when the user submits erroneous values, the form is repopulated minus the added fields. How can you retain the added fields?

I don't have the exact answer to your problem but you could probably iterate through all post data and add those fields to your form validation and view. You really should consider cleaning up your JavaScript for the next guy in line (or yourself, 6 months from now). Also, you're using the highlightFade plugin which is obselete (as claimed by it's creator) due to the addition of custom animations to jQuery. See if you can do something like this in your controller:
Code:
foreach($_POST as $key => $value)
{
     $data['custom_fields'][$key] = $this->input->post($key);  //get each form field to pass back to the view
     $this->form_validation->set_rules($key, $key, '');  //set a validation rule for each form field (or blank for no validation)
}

$this->load->view('form_page', $data);  //call your view

Then in your view you'd just iterate through the custom_fields and echo out form elements. I haven't tested this but you should be able to get something like it to work. I'm not sure how you'd manage setting real labels for each field in the form validation, or how you'd present each form field in the view, but I guess depending on your app maybe something more generic would work. That's for you to figure out.

Good luck.
#3

[eluser]gigas10[/eluser]
Hmmm, i tried to wrap everything in the code tags, sorry about that. I realize it's hard to understand what I'm saying, but I don't exactly know how to word however I you did understand what I was saying. The javascript code is crap, because believe it or not, I could not find any examples of how to add/remove fields. I searched for a couple of hours, until trying this which works... kinda. I guess I just don't understand, if I name the form element as an array, it should post an array of data. So when it comes back, shouldn't it still be an array?

PS -
Of course I'm a microsoft junkie, I have to use IIS and MSSQL at work. At home, right now, I'm running Gentoo as my OS of choice :-D. As for the non-standard double quotes... idk I use netbeans with php for my IDE Tongue
#4

[eluser]slowgary[/eluser]
My brain is on fire. I need sleep and your JavaScript is causing John Resig to turn over in his grave, and he's still alive! ;-P It's really just the inconsistent whitespace that makes it so hard to read. You really should try to stick with uniform, tabbed indents and try to write your code like you're drawing a picture - make things lined up real nice. It helps when trying to understand the code.

What is this supposed to do?
Code:
id = (id - 1) + 2;  //adds 1?  id++ would be easier

Also, it looks like you're using the hidden "id" input to hold a value. I used to do that back in the day before I realized that's what variables were for. Make it a global variable if you need to access it across functions.

You said you're allowing the user to add a form field, but the field is a select element, is that really necessary? I think you could make things easier on yourself if you went back to the drawing board on your UI. Since each select element is going to offer the same options, why not have just one select element and a button that adds the selection to a list? Make sense?

It would look like this:
Code:
,-------------------------,---,  ,--------,
| choose a root cause...  | v |  | add >> |
'-------------------------'---'  '--------'
===========================================

1. root cause numero uno [remove]

2. another root cause [remove]

3. real root cause [remove]

I would do it with something like this:
Code:
&lt; script type='text/javascript' &gt;
//this code assumes jquery inclusion

//assures the DOM is loaded before running this code
$(document).ready(function(){
     var num_causes = 0;

     //binds the following code to the 'click' of our button
     $('#add_cause').bind('click', function(){

          //add the form field, plus a remove link, plus a container div
          $('#causes').append("<div class='cause'>&lt;input type='text' disabled='disabled' name='cause_" + num_causes + "' value='" + $('#cause_select').val() + "'/&gt;&lt;span class='remove'>[remove]</span></div>");

          //increment out cause counter
          num_causes++;

     });

     //bind the following code to all current and future elements with class 'remove'
     $('.remove').live('click', function(){
          //look for a parent element with class 'cause' and remove it from the DOM
          $(this).parents('.cause').remove();

          //decrement our cause counter
          num_causes--;
     });

});
< /script >

&lt;body&gt;
<select id='cause_select' name='cause_select'>
     <option value='first'>first</option>
     <option value='second'>second</option>
     <option value='third'>third</option>
     <option value='fourth'>fourth</option>
</select>
<button id='add_cause'>add &amp;raquo;</button>
&lt;form action='somescript' method='post'&gt;
     <div id='causes'>
     </div>
     <div>
          &lt;input type='submit' value='Add Record'/&gt;
     </div>
&lt;/form&gt;
&lt;/body&gt;
Throw in some CSS and you're good to go. You'd still need to figure out the validation part, but I think it's easier once you're dealing with just a bunch of text inputs. I tested this example out and it works nicely, but as I mentioned it needs to be dressed up a bit.
#5

[eluser]gigas10[/eluser]
fyi i didn't write any of that javascript, google gave that to me, i was also wondering why the hell the author of it would do id=id-2+1... that makes no sense. I was just too lazy to change it.
#6

[eluser]slowgary[/eluser]
At least be honest. The function names in your JS match the context of your PHP.

Have you read my post? Did you take my revised UI into consideration? If not, copy and paste it into a page and see it in action. I think you'll find it better than creating a new select element for each field. Let me know what you think.
#7

[eluser]gigas10[/eluser]
This is me being honest,
http://mohdshaiful.wordpress.com/2007/05...ng-jquery/

All I did was change the name of the function and div's.... because I have more then 1 type of field that are going to be like this. I changed the function names and stuff, but I never touched the id increment, I don't exactly know what half these $ and (.' are for or do, so I figured the author must have had good reason to do that id increment like that. Yes, I did try your code, but its not what I need because it grabs the value, which for me is an ID, which does nothing for the user, if theres a way to display the name, I could also use a hidden field for the ID. If you know a way to display the name, im guessing its something to do with $('.cause_select').val()
#8

[eluser]slowgary[/eluser]
Ouch, what a nasty blog post. There's some real bad advice to be gotten out here on the interweb. Hopefully the advice I've given is much better, but everyone makes mistakes.

As a quick jQuery primer, the framework encourages that you write your javascript in a "select something, do something" sort of way. the dollar sign is a function that's used for (among other things) the selecting part, and the method that follows usually takes care of the doing.

As an example:
Code:
// v- select something
$('#my_id').hide();
           // ^- do something
That code would hide an element with the id "my_id". By "hide" I mean it sets it's CSS 'display' property to the value 'none'.

When I wrote the revised UI, I just did a quick and dirty, assuming that the option value and caption could be the same. If you need them to be unique, try changing that long append line to this:
Code:
$('#causes').append("<div class='cause'>&lt;input type='hidden' name='cause_" + num_causes + "' value='" + $('#cause_select').val() + "'/&gt;&lt;span>" + $('#cause_select:selected').text() + "</span><span class='remove'>[remove]</span></div>");
#9

[eluser]gigas10[/eluser]
I also don't understand why you are doing name='cause_"+num_causes ... why not just make the name an array, name='root_causes[]' and on the recieveing page, foreach through it. Also #cause_selectConfusedelected').text() doesn't work :-(
#10

[eluser]slowgary[/eluser]
Sure, you could do the array thing to. Then you'd just get rid of the iterator altogether. The reason the "Confusedelected" modifier didn't work is because it actually needs a space before it. I cleaned up the demo a bit, added some styles, used prepend instead of append so that new additions appear at the top, plus I made the submit button appear dynamically so that the form can only be submitted after a field is added. Try this:
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

&lt;html &gt;

&lt;head&gt;
    &lt;title&gt;&lt;/title>
    &lt;meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1' /&gt;
    &lt;style type='text/css'&gt;
        body {
            font-family: sans-serif;
        }

        .cause {
            position: relative;
            width: 200px;
            padding: 10px;
            margin: 5px 0px;
            background: #EEE;
            border: 1px solid #DDD;
        }

        select {
            padding: .15em;
            font-size: medium;
            margin-bottom: 20px;
        }

        #submit {
            width: 200px;
            padding: 10px;
            background: #EEE;
            border-top: 1px solid #CCC;
        }

        button {
            cursor: pointer;
            color: #FFF;
            padding: .2em .3em;
            line-height: 1em;
            font-size: medium;
            font-weight: bold;
            background: #59983B;
            border: 1px outset #59983B;
        }

        #submit input {
            cursor: pointer;
            color: #FFF;
            padding: 5px 10px;
            font-size: small;
            font-weight: bold;
            background: #3B5998;
            border: 1px outset #3B5998;
        }

        .remove {
            position: absolute;
            top: 50%;
            right: 15px;
            cursor: pointer;
            padding: 2px 4px;
            margin-top: -.8em;
            color: #999;
            font-size: 11px;
        }

        .remove:hover {
            color: #F00;
            background: #FCC;
        }
    &lt;/style&gt;
    &lt; script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js' &gt;&lt; /script >
    &lt; script type='text/javascript' &gt;
        //this code assumes jquery inclusion

        //assures the DOM is loaded before running this code
        $(document).ready(function(){

             //binds the following code to the 'click' of our button
             $('#add_cause').bind('click', function(){

                  if($('.cause').length == 0)
                  {
                       $('#causes').append("<div id='submit'>&lt;input type='submit' value='Add Record'/&gt;&lt;/div>");
                  }

                  //add the form field, plus a remove link, plus a container div
                  $('#causes').prepend(
                       "<div class='cause'>&lt;input type='hidden' name='causes[]' value='" +
                       $('#cause_select').val() +
                       "'/&gt;&lt;span>" +
                       $('#cause_select :selected').text() +
                       "</span><span class='remove'>[remove]</span></div>"
                  );
             });

             //bind the following code to all current and future elements with class 'remove'
             $('.remove').live('click', function(){
                  //look for a parent element with class 'cause' and remove it from the DOM
                  $(this).parents('.cause').remove();

                  if($('.cause').length == 0)
                  {
                       $('#submit').remove();
                  }
             });

        });
    &lt;/ script &gt;
&lt;/head&gt;

&lt;body&gt;
<select id='cause_select' name='cause_select'>
     <option value='first'>first cause</option>
     <option value='second'>second cause</option>
     <option value='third'>third cause</option>
     <option value='fourth'>fourth cause</option>
</select>
<button id='add_cause'>+</button>
&lt;form action='somescript' method='post'&gt;
     <div id='causes'>
     </div>
&lt;/form&gt;
&lt;/body&gt;

&lt;/html&gt;




Theme © iAndrew 2016 - Forum software by © MyBB