1
votes

I have a form, part of which has tabular input for milestones with an ajax function to add a new row.

Here's the function the ajax calls:

public function actionNewMilestoneRow($index)
{
  $milestoneModel = new TgifMilestone;
  $this->renderPartial('_milestone', array(
    'milestoneModel' => $milestoneModel,
    'i' => $index,
  ),false,true);
}

Here's the table portion of the view with the JS to add an extra row:

  <table class="timeline">
  <tbody class="milestones">
  <tr><th>Milestone</th><th>Expected<br />Completion Date</th></th></tr>
  <?php foreach ($milestoneModels as $i=>$milestoneModel): ?>
  <tr>
  <td><?php echo $form->textField($milestoneModel,"[$i]milestone",array('size'=>75,'maxlength'=>250)); ?>
  <?php echo $form->error($milestoneModel,"[$i]milestone]"); ?>
  </td>
  <td>
  <?php
  $date_value=empty($milestoneModel->expected_completion_date)?date('l, M j, Y'):$milestoneModel->expected_completion_date;
  $this->widget('zii.widgets.jui.CJuiDatePicker',array(
      'model'=>$milestoneModel, //Model object
      'language'=>'',
      'attribute'=>"[$i]expected_completion_date", //attribute name
      'options'=>array(
        'dateFormat' => 'DD, M d, yy',// equivalent to PHP date 'l, M j, Y'
        'defaultDate'=>$date_value,//see above
      ), // jquery plugin options
  ));
  ?>
<?php echo $form->error($milestoneModel,"[$i]expected_completion_date"); ?>
</td>
</tr>    <?php endforeach; ?>
</tbody>
</table>

<?php echo CHtml::button('Add Another Milestone', array('class' => 'milestone-add')) ?>    
<script>
$(".milestone-add").click(function(){
  $.ajax({
    success: function(html){
      $(".milestones").append(html);
    },
    type: 'get',
    url: '<?php echo $this->createUrl('newMilestoneRow');?>',
    data: {
      index: $(".milestones tr").size() - 1
    },
    cache: false,
    dataType: 'html'
  });
});    
</script>

Everything works fine for an added row if I render partial without the return and processoutput:

  $this->renderPartial('_milestone', array(
    'milestoneModel' => $milestoneModel,
    'i' => $index,
  ));

except that the datepicker does not show, but the table renders correctly.

When I add return and process output I get the datepicker but it breaks the table:

  $this->renderPartial('_milestone', array(
    'milestoneModel' => $milestoneModel,
    'i' => $index,
  ),false,true);

The table row and table cell tags disappear:

<tr><!-- this is the row befoe the added row -->
<td><input id="TgifMilestone_4_milestone" type="text" name="TgifMilestone[4][milestone]" maxlength="250" size="75"></td>
<td><input id="TgifMilestone_4_expected_completion_date" class="hasDatepicker" type="text" name="TgifMilestone[4][expected_completion_date]"></td>
</tr>
<link href="/requests/assets/f73aa0bb/jui/css/base/jquery-ui.css" type="text/css" rel="stylesheet">
<input id="TgifMilestone_5_milestone" type="text" name="TgifMilestone[5][milestone]" maxlength="250" size="75">
<input id="TgifMilestone_5_expected_completion_date" class="hasDatepicker" type="text" name="TgifMilestone[5][expected_completion_date]">
</tbody>
</table>

without the return and process output it renders like this:

<tr>
<td><input id="TgifMilestone_5_milestone" type="text" name="TgifMilestone[5][milestone]" maxlength="250" size="75"></td>
<td><input id="TgifMilestone_5_expected_completion_date" type="text" name="TgifMilestone[5][expected_completion_date]"></td>
</tr>
</tbody>
</table>

Any ideas how to fix it so I get both the table row and the datepicker for the added row?

Adding _milestone.php partial view at bool.dev's request;

<tr>
<td><?php echo CHtml::activeTextField($milestoneModel,"[$i]milestone",array('size'=>75,'maxlength'=>250)); ?></td>
<td>
<?php
$date_value=empty($milestoneModel->expected_completion_date)?date('l, M j, Y'):substr($milestoneModel->expected_completion_date,0,10);//default date must be a date not a datetime
  $this->widget('zii.widgets.jui.CJuiDatePicker',array(
      'model'=>$milestoneModel, //Model object
      'language'=>'',
      'attribute'=>"[$i]expected_completion_date", //attribute name
      'options'=>array(
        'dateFormat' => 'DD, M d, yy',// equivalent to PHP date 'l, M j, Y'
        'defaultDate'=>$date_value,//see above, date not datetime..

      ), // jquery plugin options

));
?> 
</td>
</tr>
1
can you show your _milestone.php partial view?bool.dev
added as requested. I use the default date for a datetimepicker also hence the cruftsdjuan

1 Answers

1
votes

The problem here is that processOutput is loading jquery.js, jquery-ui.min.js, and jquery-ui.css again, which results in the incorrect elements. Even though CJuiDatePicker needs these files, loading them once (during first rendering) is enough, and in subsequent ajax calls, we can just avoid loading them again.

To do that you can simply modify the _milestone.php partial view file:

<?php
    Yii::app()->clientScript->scriptMap['jquery.js']=false;
    Yii::app()->clientScript->scriptMap['jquery-ui.css']=false;
    Yii::app()->clientScript->scriptMap['jquery-ui.min.js']=false;
?>
<!-- rest of your _milestone.php -->

What is happening is that when processOutput encounters the registerScript calls for the above 3 files, it'll just be ignored, but the rest of the scripts (like activation) required for CJuiDatePicker will be included in the script.