Skip to content Skip to sidebar Skip to footer

Yii2- Unable To Upload Image

I am working on yii2. In one of my view, I am trying to upload an image. But I am unable to upload it. Model class MeterAcceptanceHeader extends \yii\db\ActiveRecord { public sta

Solution 1:

What looks like that you are trying to submit an image via Ajax call when you click on submit button in the step 2 for image upload as you are binding the click to the #myid which is the anchor button

<ahref="<?= URL::toRoute(['meteracceptanceheader/setpdf', 'id'=>$model->id])?>"name="redirect"class="btn btn-primary"id="myid">Submit</a>

And if you are trying to send the image via ajax you need to use the FormData interface.

The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest.send() method. It uses the same format a form would use if the encoding type were set to "multipart/form-data".

But before I address how to do it, you need to look into some other issues related to Form2 view.

  • You are nesting the 2 forms which is technically wrong and you can't do that see Why.

  • Above all why are you creating a separate form for the submit button?

    see this line on top

    <?php$form = ActiveForm::begin(['id' => 'map-form', 'enableClientValidation' => true, 'enableAjaxValidation' => false,
    'options' => ['enctype' => 'multipart/form-data']]) ?>

    This is where your first form starts and the file input field

    <?= $form->field($model, 'images[]')->fileInput(['multiple' => true, 'accept' => 'image/*'])?>

    is inside this form, and on the very next line you have the anchor button that i mentioned above in the start but you are wrapping it inside a separate form and that too before you close the ActiveForm

    <form><p><ahref="<?= URL::toRoute(['meteracceptanceheader/setpdf', 'id'=>$model->id])?>"name="redirect"class="btn btn-primary"id="myid">Submit</a><br/></p></form>

    instead you are closing the ActiveForm after this form by calling <?php ActiveForm::end(); ?>. As you have seen in the previous question that you faced weird behavior with the filter inputs for the GridVew as you were wrapping the GridView inside the form, and you are repeating that same mistake here too and also nesting 2 forms within.

What i will advise you to do first

  • Remove the form that you are creating just for the anchor button, as you wont be needing it if you want to submit the image via ajax by clicking on the anchor just keep the anchor inside the main ActiveForm. And Move the ActiveForm::begin() just before the fileInput() and after the Pjax::end().

With that said you should now user FormData to upload the image via ajax and to do so you have to add these options contentType: false and processData: false inside your ajax call and use FormData.append() to append the input files to the FormData.

So your javascript for the click function will look like this, i assume the model used for the image upload is MeterAcceptanceImages

$('#myid').on('click',function(e) {
      event.preventDefault();

      //START Append form datalet data = newFormData();

      let files= $("input[name='MeterAcceptanceImages[images][]']")[0].files;

      //append files
      $.each(files,function(index,file){
          data.append('MeterAcceptanceImages[images][]',file,file.name);
      });

      var strValue = "";
      $('input[name="selection[]"]:checked').each(function() {
           if(strValue!==""){
               strValue = strValue + " , " + this.value;
           }else{
              strValue = this.value;     
           }
      });

      //append your query string to the form data too
      data.append('data',strValue);

      //END append form data

      $.ajax({
          url: '$url',
          type: 'POST',
          dataType: 'json',
          contentType: false,
          processData: false,
          data: data,
          success: function(data) {
             alert(data);
          }
      });
});

So overall your view Form2.php should look like below

<divclass="map-meters-form"id="doc"><sectionclass="content"><divclass="box"><divid="chk"class="box-body"><?php Pjax::begin(); ?><?=
                DetailView::widget([
                    'model' => $model,
                    'attributes' => [
                        [
                            'label' => 'Serial #',
                            'value' => function($d){
                                return$d->id;
                            }
                        ],
                        [
                            'label' => 'Meter Type',
                            'value' => function ($d){
                                if( is_object($d) )
                                    return$d->meter_type;
                                return' - ';
                            },
                        ],
                        'sub_div',
                        [
                            'label' => 'Sub Division Name',
                            'value' => function ($d){
                                if( is_object($d) )
                                    return$d->subDiv->name;
                                return'-';
                            },
                        ],
                        [
                            'label' => 'Prepared By',
                            'value' => function ($d){
                                if( is_object($d) )
                                    return$d->prepared->name;
                            },
                        ],
                        'prepared_at',
                        'status',
                    ],
                ])
                ?><br><divclass="pre-scrollable"><?=
                    GridView::widget([
                        'dataProvider' => $dataProvider,
                        //'ajaxUpdate'       => true,'filterModel' => false,
                        //'id'=>'gv','columns' => [
                            ['class' => 'yii\grid\SerialColumn'],
                            ['class' => 'yii\grid\CheckboxColumn', 'checkboxOptions' => function($d){
                                    return ['value' => $d['meter_id']];
                                }],
                            'Meter_Serial_Number',
                            'Meter_Type',
                            'Sub_Division_Code',
                            'Sub_Division_Name',
                        ],
                    ]);
                    ?></div><?php Pjax::end(); ?><?php$form = ActiveForm::begin(['id' => 'map-form', 'enableClientValidation' => true, 'enableAjaxValidation' => false,
                            'options' => ['enctype' => 'multipart/form-data']])
                ?><?=$form->field($model, 'images[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?><br><p><ahref="<?=URL::toRoute(['meteracceptanceheader/setpdf', 'id' => $model->id]) ?>"name="redirect"class="btn btn-primary"id="myid">Submit</a><br/></p><?php ActiveForm::end(); ?></div></div></section></div><?php$url = Url::toRoute(['/meteracceptanceheader/setpdf', 'id' => $model->id]);
$script = <<< JS
  $(document).ready(function () {  

  $(document).on('pjax:end', function() {
    $("#chk").find("input:checkbox").prop("checked", true);
  });
  $("#chk").find("input:checkbox").prop("checked", true);

$('#myid').on('click',function(e) {
      event.preventDefault();

      //START Append form data
      let data = new FormData();

      let files= $("input[name='MeterAcceptanceImages[images][]']")[0].files;

      //append files
      $.each(files,function(index,file){
          data.append('MeterAcceptanceImages[images][]',file,file.name);
      });

      var strValue = "";
      $('input[name="selection[]"]:checked').each(function() {
           if(strValue!==""){
               strValue = strValue + " , " + this.value;
           }else{
              strValue = this.value;     
           }
      });

      //append your query string to the form data too
      data.append('data',strValue);

      //END append form data

      $.ajax({
          url: '$url',
          type: 'POST',
          dataType: 'json',
          contentType: false,
          processData: false,
          data: data,
          success: function(data) {
             alert(data);
          }
      });
});

  });
JS;
$this->registerJs($script, \yii\web\View::POS_END);
?>

Now if you try to print_r(UploadedFile::getInstances('images')) should show you all the images you selected and submitted to upload. To troubleshoot in case of errors while uploading of the ajax call you can see my answer i posted previously related to ajax file uploads.

Post a Comment for "Yii2- Unable To Upload Image"