tags:

views:

211

answers:

3

I have a form containing some dynamic elements. These are basically text input boxes that will contain phone numbers with a button to the right to delete the element. Another button adds a new element and the final one to save it to the database. What I'm wanting to do is to "mark" numbers that have changed, been removed or new numbers. So that I can do a update, insert or delete on the database as I don't want to delete all and insert all each time in the database.

The delDisaNumber isn't quite what I want... I want to hide the element so I can mark it as deleted. But doing so makes it appear like the form gets submitted. On the other hand, using .remove visibly behaves how I want it to, but removes the element completely which is not what I want (I want it hidden).

Here is the code in question so far. (this is written in jquery and php using kohana)

<script type="text/javascript">
  var disaId = 1;

  function setModified(element){
    $(element).attr('name', 'update');
  }

  function delDisaNumber(element){
      $(element).prev('name','delete');
      $(element).parent().remove();  /* has the effect I want, but removes the element */
      // $(element).parent().hide() /* this is what I want but submits the form */
  }

  function addDisaNumber(){
      $("#disa_numbers").append('<li id="disa_num"'+disaId+'><input /><button onClick="delDisaNumber">X</button></li>');
    $disaId++;
  }
  </script>

  ...

<div id="disa">
  <?php
    echo form::open("edit/saveDisaNumbers/".$phone, array("class"=>"section", "id"=>"other"));
    echo form::open_fieldset(array("class"=>"balanced-grid"));
  ?>
  <ul class="fields" id="disa_numbers">
    <?php
      $disaId = 1;
        foreach ( $disa_numbers as $disa_number ){
           $disaid_name = 'disa_num'.$disaId;
           echo '<li id="'.$disaid_name.'">';
           echo form::input("disa".$disaId, $disa_number->cid_in, "onKeyDown='setModified(this)'");
           echo form::button("",'X','onClick="delDisaNumber(this)" class="button image"');
           echo "</li>";
           $disaId++;
        }
     ?>   
    </ul>
    <button type="button" onclick="addDisaNumber()">Add another number</button>
    <?php
      echo form::submit('submit', 'Save');
      echo form::close();
    ?>
</div>

EDIT: It seems that form::button isn't behaving as expected. If I replace it with echo 'X' it doesn't post the form.

+1  A: 

My suggestion is that instead of changing the name, add a class like "modified". And then submit only those.

$("form").submit(function() {
  $("input:not(.modified)").attr("disabled", true);
});

How this works is that disabled input elements aren't submitted to the server.

cletus
Sounds good, could you please give a fuller example of that?
Matt H
A: 

inside delDisaNumber

$(element).parent().css("visibility", "hidden");
F.Aquino
A: 

Hi Matt, I think there are several ways to solve your problem.

This one may be faster and a little bit more elegant. You will need to create an array of actions and then submit them through AJAX to the server. Let me explain:

suppose your "phone" fields are with the class "phone" and a wrapper DIV with an "id": Example: (The id can be your DB's id or the phone with a prefix(like I show). Or if you prefer, you can add them first to an array and assign a temporally id. That way you can verify the changes at the end).

<div id="p_18003526445">
    <input type="text" class="phone" value="1800-3526-445" />
    <button class="del">Delete</button>
</div>
...
<button id="add">Add More...</button>  
<button id="save">Save Changes</button>  

Now the JQuery:

var phones = new Array();
var new_id = 0; //keep track of added ids
$(window).load(function() {
    $("input.phone").change(function() { 
         //you could check here if the phone id is the same as the val... (and skip)
         phones[$(this).parent().attr("id")] = $(this).val();             
    });
    $("button.del").click(function() {
         var id = $(this).parent().attr("id");
         $(this).prev("input.phone").val("deleted"); //setting to "deleted"
         $("#"+id).hide(); //hide the DIV (input + button)
    });
    $("#add").click(function() {
         new_id++;
         $("#main").append("<div id='n_"+new_id+"'>
             <input type='text' class='phone' />
             <button class='del'>Delete</button>
         </div>");
    });
    $("#save").click(function() {
         $.post("save.php",{ phones : $.toJSON(phones) },
             function(reply, status){
                  if(status == "success" && reply == "OK") {
                       alert("UPDATED!");
                  } else {
                       alert("ERROR: Try again");
                  }
             }
         );
    });
});

Now in you "save.php" you will need to execute something like:

<?php
   $import = json_decode($_POST["phones"]);
   if($import) {
    $phones = array();
    foreach($import as $i => $p) {
         $phones[$i] = $p;
    }
   }
   //print_r($phones);
   ...
   echo "OK"; //Tell JQuery everything went fine!
?>

In you PHP you will have an array now with the ID and action to do. If the action is "deleted" you proceed to delete it (remember that the ID will be p_#####), if its a number, then update and if the ID starts with "n_" then its new. Other way is to create 3 arrays separated one for update, one for delete and one for insert and send them separately. But I decided to do it this way for simplicity. Additionally you could perform some checks before sending the list.

You don't need the "form" tag anymore neither the javascript actions inside your tags. I recommend you to use the JSON Jquery plugin if you want fully compatibility (JQuery -> PHP).

This code is untested and unfinished, it is just the idea... you will need to implement it. If you want you can add some JQuery UI dialog to display "Please wait..." while the form is transmitted to the server.

If you want to keep going with your approach, you could always change the input TYPE:

$("#disa_num input").attr("type","hidden"); 

and append to the form another input "hidden" with the actions, or prepend to the value an identifier of the action like:

var oldvalue = $("#disa_num input").val();
$("#disa_num input").val("d-"+oldvalue); //prepend "d-" to identify it as "deleted"

That's it.. I hope its useful.

lepe