Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

PHP

Dynamicly add data to a hidden field

Hello everyone.

I kinda a newbie to php and I use codeigniter as my framework. This question is not about Codeigniter, but more of a php question. I have no idea how to solve this case. If anyone has an idea, that would be great

The problem: I have a table with data that comes from a database. For each row there is a button which opens a bootstrap-modal form dialog. In order to be able to add the data back to the database there shall be a hidden form field with the users id.

Question: How do I dynamically add data to the form field?

Data displayed in a table

if (is_array($results)) {

    foreach($results as $data) {
        echo '<tr>';
        echo '<td>'.$data->id.'</td>';
        echo '<td>'.$data->company.'</td>';
        echo '<td>'.$data->first_name.'</td>';
        echo '<td>'.$data->last_name.'</td>';
        echo '<td>'.$data->position.'</td>';
        echo '<td>'.$data->email.'</td>';
        echo '<td>'.$data->phone.'</td>';
        echo '<td>'.$data->street.'</td>';
        echo '<td>'.$data->city.'</td>';
        echo '<td>'.$data->postal_code.'</td>';
        echo '<td>'.$data->date.'</td>';
        echo '<td>'.$data->notes.'</td>';
        echo '<td>'.$data->date_created.'</td>';
        echo '<td>  

             <!-- Single button -->
                <div class="btn-group">
                  <button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown">
                    Update Status <span class="caret"></span>
                  </button>
                  <ul class="dropdown-menu" role="menu">
                    <li>'.anchor('today/update_contact_status/lead/'.$data->id, 'Lead' , $data->id).'</li>
                    <li><a href="#" data-toggle="modal" data-target="#callAgain">Contacted (call again)</a></li>
              <li>'.anchor('today/update_contact_status/meeting/'.$data->id, 'Meeting' , $data->id).'</li>
              <li>'.anchor('today/update_contact_status/client/'.$data->id, 'Is now client' , $data->id).'</li>
              <li>'.anchor('today/update_contact_status/onhold/'.$data->id, 'On Hold' , $data->id).'</li>
                    <li class="divider"></li>
              <li><a href="#" data-toggle="modal" data-target="#callAgain">Contacted (call again)</a></li>

               <li class="divider"></li>
              <li>'.anchor('today/delete_contact/'.$data->id, 'delete' , $data->id).'</li>


                  </ul>
                </div>
               </td>';
        echo '<td>'.'<button type="button" class="btn btn-default" data-toggle="modal" data-target="#addNote">Add Note</button>'.'</td>';
        echo '</tr>';

}

} else {

  echo '  <div class="alert alert-danger">
          <strong>Oh snap!</strong> Nothing todo for today! </div> ';
}

?>
</table>

 ** 

*and the modal: *

<!-- Modal -->
 <?php echo form_open('today/add_contact_record'); ?>
<div class="modal fade" id="callAgain" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
        <h4 class="modal-title" id="myModalLabel">Call again</h4>
      </div>
      <div class="modal-body">

      <?php echo form_hidden('username', 'johndoe'); ?>

            <div class="form-group">
        <?php echo form_label('Date','', $labelattributes); ?>
        <div class="input-group date form_date col-md-12" data-date="" data-date-format="dd MM yyyy" data-link-field="dtp_input2" data-link-format="yyyy-mm-dd">
        <?php echo form_input($date); ?>
                   <span class="input-group-addon"><span class="glyphicon glyphicon-remove"></span></span>
                   <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
        <?php echo form_error('Date'); ?>
         </div> 
     </div>

    <div class="form-group">
        <?php echo form_label('Time','', $labelattributes); ?>
                <div class="input-group date form_time col-md-12" data-date="" data-date-format="hh:ii" data-link-field="dtp_input3" data-link-format="hh:ii">
        <?php echo form_input($time); ?>
                    <span class="input-group-addon"><span class="glyphicon glyphicon-remove"></span></span>
                    <span class="input-group-addon"><span class="glyphicon glyphicon-time"></span></span>
        <?php echo form_error('Time'); ?>
         </div> 
     </div>
<?php echo form_textarea($notes); ?>

      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <?php  echo form_submit('submit', 'Submit', 'class="btn btn-default btn-lg", type="button"');    ?>
      </div>
    </div>
  </div>
  <?php echo form_close();?>
</div>

17 Answers

Ok, so I see you figured out .next() in order to obtain the second td containing the employeeID. That part looks good.

What we need to change is how the hidden input is selected because there are two hidden inputs now. selecting input[type="text"] isn't enough to tell them apart because they both have that. What's different about them is their name attribute. So we can change that attribute selector to use name instead of type

I'll assume the following hidden inputs:

<input type="hidden" name="companyID" value="">
<input type="hidden" name="employeeID" value="">

Here's the updated script without the alerts:

<script type="text/javascript">
      $('button[data-target="#addNote"]').click(function() {
      var companyID = $(this).parent().siblings(":first").text();
      var employeeID = $(this).parent().siblings(":first").next().text();

      $('#addNote input[name="companyID"]').val(companyID);
      $('#addNote input[name="employeeID"]').val(employeeID);

      });

      $('a[data-target="#callAgain"]').click(function(e) {
      e.preventDefault();
      var companyID = $(this).parents("td").siblings(":first").text();
      var employeeID = $(this).parents("td").siblings(":first").next().text();

      $('#callAgain input[name="companyID"]').val(companyID);
      $('#callAgain input[name="employeeID"]').val(employeeID);

      });
      </script>

I didn't test this so let me know if there are any problems.

Let me see first if I understand the problem correctly.

Each row has an "Add Note" button and a different $data->id value. When the user clicks a certain "Add Note" button you want the corresponding id to be placed into the value attribute of the following hidden form field:

<?php echo form_hidden('username', 'johndoe'); ?>

I'll try to give you an answer based on that. I'll update my answer if you're trying to do something else instead.

I think you can write a click handler for the buttons and then retrieve the user id for that row and write it out to the hidden input.

This is the jQuery I came up with. It assumes only one hidden input field on the page. If you have others then we'll have to change the selector for that hidden input. I don't know how much jQuery you know so let me know if you need an explanation of the code.

$('button[data-target="#addNote"]').click(function() {
  var userId = $(this).parent().siblings(":first").text();
  $('input[type="hidden"]').val(userId);
});

I did a codepen for a proof of concept so you can verify that it's doing what you want before you put it into your code. I stripped down the html to what I thought was essential for the problem.

http://codepen.io/anon/pen/sjIfz/

You'll have to use your browser's developer tools if you want to see the input value changing as you click each of the buttons. You'll need to inspect the form element and then watch the value as you click the buttons. I use firebug in firefox.

We'll have to see if this code still works correctly when the modal is called up.

Hi Jason.

Thank you very much for your answer. Your assumptions were right. Unfortunately I am not familiar at with jquery at all.

So I added this instead of the hidden field:

´´´ <script> $('button[data-target="#callAgain"]').click(function() { var userId = $(this).parent().siblings(":first").text(); $('input[type="hidden"]').val(userId); }); </script> ´´´

But how does this refer to the ´´´$data->id´´´?

Hi Dennis,

After I posted I realized I had some confusion on this. You're calling up two different modals on that page. You have a couple links that are calling up the "call again" modal and then your "add note" button was calling up an "addNote" modal. The modal that you posted on the page looks like it's the call again modal based on its' id and the modal title of "Call again"

Is the modal you posted supposed to be the "addNote" modal but your forgot to change the id and title?

I can explain the jQuery to you but I'd like to clear up my confusion on this first in case the jQuery needs to be changed.

Also, do you only have the one hidden input field on the page?

Another thing I should point out is that I don't believe the output html for your modal dialog would validate.

You're opening your form before the first modal div and then closing the form before the last closing div.

So I think you have a situation like this:

<form> <div> </form> </div>

Which wouldn't be valid html. View the source of your html in the browser to see if that's the case.

All of your modal content should be inside the modal-body div. I recommend that you open and close your form within that div. This way your submit button will also be up there with your form inputs instead of down next to the close button in the modal footer. By having those two buttons close together you risk having the user click on the wrong one.

I would suggest doing your dialog like this:

<!-- Modal -->
<div class="modal fade" id="callAgain" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
        <h4 class="modal-title" id="myModalLabel">Call again</h4>
      </div>
      <div class="modal-body">
<?php echo form_open('today/add_contact_record'); ?>
      <?php echo form_hidden('username', 'johndoe'); ?>

            <div class="form-group">
        <?php echo form_label('Date','', $labelattributes); ?>
        <div class="input-group date form_date col-md-12" data-date="" data-date-format="dd MM yyyy" data-link-field="dtp_input2" data-link-format="yyyy-mm-dd">
        <?php echo form_input($date); ?>
                   <span class="input-group-addon"><span class="glyphicon glyphicon-remove"></span></span>
                   <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
        <?php echo form_error('Date'); ?>
         </div> 
     </div>

    <div class="form-group">
        <?php echo form_label('Time','', $labelattributes); ?>
                <div class="input-group date form_time col-md-12" data-date="" data-date-format="hh:ii" data-link-field="dtp_input3" data-link-format="hh:ii">
        <?php echo form_input($time); ?>
                    <span class="input-group-addon"><span class="glyphicon glyphicon-remove"></span></span>
                    <span class="input-group-addon"><span class="glyphicon glyphicon-time"></span></span>
        <?php echo form_error('Time'); ?>
         </div> 
     </div>
<?php echo form_textarea($notes); ?>
<?php  echo form_submit('submit', 'Submit', 'class="btn btn-default btn-lg", type="button"');    ?>
  <?php echo form_close();?>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>

Hi Jason.

Thanks for answering. The intention of this form is to create kind of a call/to-do list.

There are indeed two modals, that are called through the buttons.

The callagain-Button/Modal. There is a time, date and note field which will be added to database. In order to reference it for the update query I would need the user's id in a hidden field.

If I would find a working example I might be able to adapt it myself.

Ok, I see that the modal you posted contains the fields you mentioned.

Originally I thought you said that you're going to be clicking on the "Add Note" button to bring up this dialog. But the data-target of that button and the id of the modal don't match up.

In your table row you have a drop down which contains a couple of anchor links whose data-target does matchup with the modal you posted.

Is it those links that are going to activate this modal?

<a href="#" data-toggle="modal" data-target="#callAgain">Contacted (call again)</a>

Is that what you're going to be clicking on in order to activate the modal? Not the "Add note" button that is in the last cell of your row?

I need to update the jQuery if that's the case.

Also, you have two of those links in that dropdown. Do they both perform the same action regardless of which link you clicked?

Hi Jason.

Thanks for answering. Indeed there are two modals.

One for adding date, time and a note (textarea) and another one for just adding a note. When clicking on submit in these modals an update query gets launched.

Ok, so both modals will be saving data back to the server and you need the userId in each one.

Does this mean both of your modals have a hidden input field that needs to contain the userId?

yes. that's correct.

Edit: fixed some typos

This jQuery code should work for the "Add note" button. I've changed the selector for the hidden input now that i know there's two on the page.

$('button[data-target="#addNote"]').click(function() {
  var userId = $(this).parent().siblings(":first").text();
  $('#addNote input[type="hidden"]').val(userId);
});

It selects all the buttons that have a data-target attribute equal to "#addNote". It then assigns a click handler to all of those buttons and passes in a function which will be executed each time one of the buttons is clicked.

We need to know which button was clicked so we can retrieve the corresponding id. $(this) refers to the button that was clicked. At this point it's a matter of navigating the dom hierarchy to get to that first <td> which contains the id in question.

parent() will get us up to the td that contains the button.

siblings(":first") will select all of the other td siblings and then filter it down to the first td.

text() will give us the text of that td which is the userId and then I'm storing that in the userId variable.

Then it's selecting the hidden input that is within the modal with an id of "AddNote" and setting the value to the userId.

We also need to do this for the "call again" links but navigating the dom will be a little different because those links are nested deeper into the <td>

$('a[data-target="#callAgain"]').click(function(e) {
e.preventDefault();
  var userId = $(this).parents("td").siblings(":first").text();
  $('#callAgain input[type="hidden"]').val(userId);
});

The only difference here is that we're selecting links with a data-target of #callAgain. Since it's a link we're clicking, we need to prevent the default link action. Then the navigation to the first td is different.

I didn't test this second one so let me know if it doesn't work.

Both of these click handlers should be placed inside a script tag probably before your closing body tag.

Let me know what the results are.

Hi Jason.

Thanks for your explanations. Unfortunately the hidden field is populated with the value of userId, not the number

Here is the code in modal right now:

<?php echo form_hidden('userId', 'userId'); ?>

    <script type= text/javascript>
      $('a[data-target="#callAgain"]').click(function(e) {
      e.preventDefault();
        var userId = $(this).parents("td").siblings(":first").text();
        $('#callAgain input[type="hidden"]').val(userId);
      });
       </script>

and

    <?php echo form_hidden('userId', 'userId'); ?>

    <script type= text/javascript>
      $('a[data-target="#callAgain"]').click(function(e) {
      e.preventDefault();
        var userId = $(this).parents("td").siblings(":first").text();
        $('#callAgain input[type="hidden"]').val(userId);
      });
       </script>

Ok, we'll have to start troubleshooting. I feel we're on the right track though because I had it working in the codepen demo.

The two modals are on the same page as the table, correct? Does the table markup appear before the modal markup?

First, you can combine the two scripts into one and move them down to right before the closing body tag. I don't know how codeigniter works so if your closing body tag is not on that page because it's in a footer include file then try moving it to right before you include that footer.

<script type= text/javascript>
$('button[data-target="#addNote"]').click(function() {
alert('Clicked the Add note button');
var userId = $(this).parent().siblings(":first").text();
alert(userId);
$('#addNote input[type="hidden"]').val(userId);
});

$('a[data-target="#callAgain"]').click(function(e) {
alert('Clicked the call again link');
e.preventDefault();
var userId = $(this).parents("td").siblings(":first").text();
alert(userId);
$('#callAgain input[type="hidden"]').val(userId);
});
</script>

I've temporarily inserted alert statements so that you can see if the clicking is even working and also another alert to show what the userId is.. And we can go from there.

Secondly, did you move your entire form into the modal-body like I mentioned in an earlier answer? This could be causing you problems plus you run the risk of not every browser being able to render that correctly.

So let's see if you see the alert popups or not.

Is your modal dialog coming up properly?

Hi Jason. The jquery script works correctly and I get the right alerts displayed. But how do I get the data in to a hidden field?

Ok, so if the second alert is displaying the correct userId then we know we've retrieved that correctly. The last line should be setting that value in the hidden input. $('#addNote input[type="hidden"]').val(userId);

It was working correctly in that earlier codepen demo I gave you. Do I have the selector wrong? #addNote input[type="hidden"] This should be selecting an input with a hidden type that is within an element with an id of "addNote" That matches up with your markup doesn't it?

How are you verifying that the data isn't going into the hidden input field?

Are you using developer tools to check the hidden input? That would be your easiest option. After the modal is displayed, you can inspect the form element and view the hidden input field to see if it's value has been updated.

Also, did you fix the markup in your modal by putting the entire form in the modal body? I don't know if that would cause the jQuery code not to work but best to eliminate that as a possibility.

Hello Jason.

Thanks for your help. What I did ist I changed the input type to text instead of hidden. So far I could see where I lose my variable. When I call my modal it is still there, but when I submit it and try to store in the database I lose my variable. But I guess that is more of an php/codeigniter problem.

Thanks a lot for your help!

HI Jason.

I managed to get it working. Thank you again for your awsome help!

Great! Did something have to be changed in the jQuery or was it on the php end?

Also, I would recommend that you get familiar with your browser's developer tools if you aren't already. It would let you view the changes in the dom in real time. This way you could watch the hidden input value changing without having to temporarily make it a text input as you had to do. I personally use firebug in firefox.

At the end it was php that did't get the value of the form.

Just a quick question: How would that code look if you would select a table data field with an id.

<td id="companyID">
<td id="employeeID">

I have modified my table structure. so now in need two id's.

Thanks in advance.

Did you apply the id attributes for the purposes of styling so those two cells can look different than the others? To be clear, are you using the string "companyID" or you are putting the actual companyID into each row?

If the id is not unique from row to row then it's invalid html. Id's have to be unique on the page.

So if this is what your markup looks like:

<tr>
    <td id="companyID"></td>
    <td id="employeeID"></td>
    <td></td>
    <td></td>
    <td></td>
</tr>
<tr>
    <td id="companyID"></td>
    <td id="employeeID"></td>
    <td></td>
    <td></td>
    <td></td>
</tr>

I would change it to this:

<tr>
    <td class="companyID"></td>
    <td class="employeeID"></td>
    <td></td>
    <td></td>
    <td></td>
</tr>
<tr>
    <td class="companyID"></td>
    <td class="employeeID"></td>
    <td></td>
    <td></td>
    <td></td>
</tr>

so this is what I ended up with. The alerts are still correct. But the form values are wrong. They only take the first value.

      <script type= text/javascript>
      $('button[data-target="#addNote"]').click(function() {
      //alert('Clicked the  Add note button');
      var companyID = $(this).parent().siblings(":first").text();
      var employeeID = $(this).parent().siblings(":first").next().text();


      alert(companyID);
      alert(employeeID);
      $('#addNote input[type="text"]').val(companyID);
      $('#addNote2 input[type="text"]').val(employeeID);

      });

      $('a[data-target="#callAgain"]').click(function(e) {
    //  alert('Clicked the call again link');
      e.preventDefault();
      var companyID = $(this).parents("td").siblings(":first").text();
      var employeeID = $(this).parent().siblings(":first").next().text();

      alert(companyID);
      alert(employeeID);

      $('#callAgain input[type="text"]').val(companyID);
      $('#callAgain2 input[type="text"]').val(employeeID);

      });
      </script>

Are you sure that the alert for employeeID shows correctly for the call again link? You don't have the same method calls as for companyID. It might be a copy/paste error from the code for the "Add note" button.

Awsome. Thank you very much. Defenetly will hit the javascript course here on treehouse.

Glad you got all the hiccups worked out.

The javascript course should help you out a lot. Also, I think it's "Build an interactive site", that one covers the basics of jQuery.