yii2-dynamicform icon indicating copy to clipboard operation
yii2-dynamicform copied to clipboard

Does not work for image uploads

Open uthpalax opened this issue 9 years ago • 26 comments

I have tried to add images dynamically using this widget but it doesn't work.

uthpalax avatar Apr 27 '15 13:04 uthpalax

How is the code in your view file?

wbraganca avatar Apr 27 '15 13:04 wbraganca

The widget works in a sense I get the dynamically created row but when submitting the files don't get submitted

['enctype'=>'multipart/form-data','id' => 'dynamic-form'], 'layout'=>'horizontal', 'fieldConfig'=> [ 'template' => "{label}\n{beginWrapper}\n{input}\n{hint}\n{error}\n{endWrapper}", 'horizontalCssClasses' => [ 'label' => 'col-sm-3', 'wrapper' => 'col-sm-8', 'error' => '', 'hint' => '', ] ] ]); ?>
<div class="row">
    <div class="col-md-4">
        <?= $form->field($model, 'title')->textInput(['maxlength' => 100]) ?>
    </div>
    <div class="col-md-4">
        <?= $form->field($model, 'district')->textInput(['maxlength' => 50]) ?>
    </div>
    <div class="col-md-4">
        <?= $form->field($model, 'area')->textInput(['maxlength' => 50]) ?>
    </div>
</div>
<div class="row">
    <div class="col-md-10 pull left">
            <?= $form->field($model, 'description')->textarea(['rows' => 3]) ?>  
    </div>
</div>
<div class="row">
<div class="col-md-12">
    <div class="panel panel-default">
        <div class="panel-heading"><h6><i class="glyphicon glyphicon-film"></i>Photo</h6></div>
        <div class="panel-body">
             <?php DynamicFormWidget::begin([
                'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
                'widgetBody' => '.container-items', // required: css class selector
                'widgetItem' => '.item', // required: css class
                'limit' => 15, // the maximum times, an element can be cloned (default 999)
                'min' => 1, // 0 or 1 (default 1)
                'insertButton' => '.add-item', // css class
                'deleteButton' => '.remove-item', // css class
                'model' => $modelsPhoto[0],
                'formId' => 'dynamic-form',
                'formFields' => [
                    'title',
                    'description',
                    'image_path',
                ],
            ]); ?>
            <div class="container-items"><!-- widgetContainer -->
            <?php foreach ($modelsPhoto as $i => $modelPhoto): ?>
                <div class="item panel panel-default"><!-- widgetBody -->
                    <div class="panel-body">
                        <button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
                        <button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
                        <?php
                            // necessary for update action.
                            if (! $modelPhoto->isNewRecord) {
                                echo Html::activeHiddenInput($modelPhoto, "[{$i}]id");
                            }
                        ?>
                        <div class="row">
                            <div class="col-sm-3">
                                <?= $form->field($modelPhoto, "[{$i}]title")->textInput(['maxlength' => true]) ?>
                            </div>
                            <div class="col-sm-5">
                                <?= $form->field($modelPhoto, "[{$i}]image_path")->fileInput(); ?>
                            </div>
                            <div class="col-sm-4">
                                <?= $form->field($modelPhoto, "[{$i}]description")->textInput(['maxlength' => true]) ?>
                            </div>

                        </div>
                    </div>
                </div>
            <?php endforeach; ?>
            </div>
            <?php DynamicFormWidget::end(); ?>
        </div>
    </div>
</div>
</div>
<div class="col-md-12 form-group">
            <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>

uthpalax avatar Apr 27 '15 13:04 uthpalax

Can you provide an answer for this I am in a tough schedule. When inspect element it generates two inputs for file one is a hidden filed and other is visible it looks this bug

uthpalax avatar Apr 28 '15 11:04 uthpalax

@Uthpala Are you using any widget to the image field?

wbraganca avatar Apr 28 '15 12:04 wbraganca

I tried two ways once with the normal fileInput and the other with karthik fileInput widget. Both are not working. The value is not getting assigned to the fileInput

uthpalax avatar Apr 28 '15 12:04 uthpalax

Okay I am going to assume that this is not going to work.

uthpalax avatar Apr 30 '15 06:04 uthpalax

i am facing the the same issue here in file upload ....

jgrasta avatar May 04 '15 03:05 jgrasta

screenshot from 2015-05-26 15 40 20 I tried to configure dynamic form with karthik fileinput. It is showing "loading" icon everytime when I click on Add- Item [+] button. Also It is giving me javascript error like Uncaught TypeError: Cannot read property 'widgetItem' of undefined ----- yii2-dynamic-form.js:199

maheshtc avatar May 26 '15 10:05 maheshtc

@maheshtc Could you post here your view code?

wbraganca avatar May 26 '15 12:05 wbraganca

My View file is big, so I am pasting only dynamic-form code.

use kartik\widgets\FileInput; use wbraganca\dynamicform\DynamicFormWidget;

Story Images

    <div class="panel-body">
         <?php DynamicFormWidget::begin([
            'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
            'widgetBody' => '.container-items', // required: css class selector
            'widgetItem' => '.item', // required: css class
            'limit' => 5, // the maximum times, an element can be cloned (default 999)
            'min' => 1, // 0 or 1 (default 1)
            'insertButton' => '.add-item', // css class
            'deleteButton' => '.remove-item', // css class
            'model' => $model,
            'formId' => 'dynamic-form',
            'formFields' => [
                'Filename',
                'FilenameDesc',
            ],
        ]); ?>

        <div class="container-items"><!-- widgetContainer -->
        <?php //for($i=1;$i<=5;$i++):?>
            <?php $filename = 'Filename[]'; $file_desc='FilenameDesc[]';
            //if($i>1 && $model->$filename && $model->$file_desc):?>
            <div class="item panel panel-default"><!-- widgetBody -->
                <div class="panel-heading">
                    <div class="pull-right">
                        <button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
                        <button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
                    </div>
                    <div class="clearfix"></div>
                </div>
                <div class="panel-body">
                    <?= $form->field($model, $file_desc)->textInput(['maxlength' => true]) ?>
                    <?= $form->field($model,$filename)->widget(FileInput::className(),[
                        'pluginOptions' => ['previewFileType' => 'image','showUpload'=>false,'browseLabel' => '',
    'removeLabel' => '',
    'mainClass' => 'input-group-lg'],
                        'options'=>['accept' => 'image/*'],
                    ]);?>
                </div>      

            </div>
            <?php //endif;?>
        <?php //endfor; ?>
        </div>
        <?php DynamicFormWidget::end(); ?>
    </div>
</div>

maheshtc avatar May 26 '15 14:05 maheshtc

@wbraganca Can you provide view file that you implemented with file input. I think I am near to solving a problem,

maheshtc avatar May 27 '15 14:05 maheshtc

The values of the variables $filename and $file_desc is incorrect.

Try this:

<?= $form->field($model, "[{$index}]fileDesc")->textInput(['maxlength' => true]) ?>
<?= $form->field($model, "[{$index}]img")->widget(FileInput::className(), [
    'options' => ['accept' => 'image/*'],
    'pluginOptions' => [
        'previewFileType' => 'image',
        'showUpload' => false,
        'browseLabel' => '',
        'removeLabel' => '',
        'mainClass' => 'input-group-lg'
    ]
]) ?>

wbraganca avatar May 27 '15 17:05 wbraganca

@wbraganca Thanks for your quick response Currently I am using same model and I am having a fields named filename and filedesc, I am planning to store filename and filedesc as json string which will be combination of multiple filename and filedesc and that is why I am using filename[] and filedesc[].

As per your example, there is different table and model for the table and using that you are cloning block of elements. So Is it possible to achieve same functionality with the same model and array of fields.

maheshtc avatar May 30 '15 08:05 maheshtc

Plugin not working for uploading Image :( Very disappointed because you are not giving solution .

ghost avatar Jun 10 '15 18:06 ghost

@amit4sky I have applied below code for uploading images

For Create Action

if ($model->load(Yii::$app->request->post())) { $ad_images = Model::createMultiple(AdImage::classname()); Model::loadMultiple($ad_images, Yii::$app->request->post());

        foreach($ad_images as $i=>$ad_image):
            $file[$i]=  UploadedFile::getInstanceByName("AdImage[".$i."][image_name]");
            if($file[$i]){
                $ext = end((explode(".", $file[$i]->name)));
                // generate a unique file name
                $size[$i] = \common\models\AdSize::findOne($ad_image->size_id);
                $ad_images[$i]->image_name= Yii::$app->security->generateRandomString()."_".$size[$i]->resolution.".{$ext}";
                $path[$i]= Yii::getAlias ('@storage') ."/uploads/ads/". $ad_images[$i]->image_name;
            }   
        endforeach;

        // validate all models
        $valid = $model->validate();
        $valid = Model::validateMultiple($ad_images) && $valid;

        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                if ($flag = $model->save(false)) {
                    foreach ($ad_images as $ad_image) {
                        $ad_image->ad_id = $model->id;
                        if (! ($flag = $ad_image->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                        else{
                            if($file[$i]){
                                $file[$i]->saveAs($path[$i]);
                                $image = Yii::$app->image->load($path[$i]);
                                $image->resize($size[$i]->width,$size[$i]->height)->save($path[$i]);
                            }
                        }
                    }
                }
                if ($flag) {
                    $transaction->commit();
                    return $this->redirect(['view', 'id' => $model->id]);
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        }
    }

Please check it out above solution and let me know if not working

maheshtc avatar Jun 11 '15 06:06 maheshtc

Hi All,

I am using yii2 dynamic form in which I use file input widget. The problem is that I cannot get any uploaded instance from the dynamic (personIdentification) form for the create action.

I uploaded the files and if you can give me a hint I would appreciate it !!!

http://pastebin.com/WnjH16Jf (_form) http://pastebin.com/ACUFQwrh (controller) http://pastebin.com/DYT92JFW (addUser model) http://pastebin.com/iMJMgkyB (personIdentification model)

cratemos666 avatar Jun 13 '15 11:06 cratemos666

I had same problem with @maheshtc , and decided like this https://github.com/bookin/yii2-dynamicform/commit/856a43824b75dbefcfd7999c3f03b21f704fc6a8

bookin avatar Sep 18 '15 19:09 bookin

Same problem. In frontend works well. In backend with same views, it does not work...

invisor avatar Mar 06 '16 15:03 invisor

I have got the same problem i change this

'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_] 'widgetBody' => '.container-items', // required: css class selector 'widgetItem' => '.item', // required: css class

to other more suitable names and all starts working.... don't know why...

So yea basically changing the default css classes and widgetContainer name do the job, I also run backend.

pliszka avatar Jul 16 '16 19:07 pliszka

please provide working for dynamic form file upload please

ryanmakinano avatar May 09 '17 01:05 ryanmakinano

@wbraganca i cant upload a image with your dynamic form file upload

ryanmakinano avatar May 09 '17 01:05 ryanmakinano

@wbraganca , I also got "unrecognized expression: #tcandidateexp-{$i}-prod_per_year_file" error when tried to upload file. The field I want to use as a file upload is "prod_per_year_file". Thanks.

` 'dynamic-form', 'options'=>['enctype'=>'multipart/form-data']]); ?>

'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_] 'widgetBody' => '.container-items', // required: css class selector 'widgetItem' => '.item', // required: css class 'limit' => 5, // the maximum times, an element can be added (default 999) 'min' => 1, // 0 or 1 (default 1) 'insertButton' => '.add-item', // css class 'deleteButton' => '.remove-item', // css class 'model' => $models_exp[0], 'formId' => 'dynamic-form', 'formFields' => [ 'start_year', 'end_year', 'company', 'prod_per_year', 'prod_per_year_file', 'inc_per_year', 'inc_per_year_file' ], ]); ?>
    <div class="panel panel-default" style="width:85%">
        <div class="panel-heading">
            <h4>
                <i class="glyphicon glyphicon-envelope"></i> Experiences
                <button type="button" class="add-item btn btn-success btn-sm pull-right"><i class="glyphicon glyphicon-plus"></i> Add</button>
            </h4>
        </div>
        <div class="panel-body">
            <div class="container-items"><!-- widgetBody -->
            <?php foreach ($models_exp as $i => $model_exp): ?>
                <div class="item panel panel-default"><!-- widgetItem -->
                    <div class="panel-heading">
                        <h3 class="panel-title pull-left">Detail</h3>
                        <div class="pull-right">
                            <button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
                        </div>
                        <div class="clearfix"></div>
                    </div>
                    <div class="panel-body">
                        <?php
                            // necessary for update action.
                            if (! $model_exp->isNewRecord) {
                                echo Html::activeHiddenInput($model_exp, "[{$i}]id");
                            }
                        ?>
                        
                        <div class="row">
                            <div class="col-sm-6" >
                                <?=                                         
                                    $form->field($model_exp, "[{$i}]start_year")->textInput();
                                ?>
                            </div>
                            
                            <div class="col-sm-2">
                                <?= 
                                    $form->field($model_exp, "[{$i}]end_year")->textInput();
                                ?>
                            </div>
                            <div class="col-sm-2">
                                <?= 
                                    $form->field($model_exp, "[{$i}]company")->textInput();
                                ?>
                            </div>
                            
                            <div class="col-sm-10">
                                <?= $form->field($model_exp, "[{$i}]prod_per_year")->textInput() ?>
                            </div>
                            
                            <div class="col-sm-10">
                                <?php 
                                    //$form->field($model_exp, "[{$i}]prod_per_year_file")->textInput()
                 echo $form->field($model_exp, '[{$i}]prod_per_year_file')->widget(FileInput::classname(), [
                                        'pluginOptions' => [
                                            'showPreview' => false,
                                            'showCaption' => true,
                                            'showRemove' => true,
                                            'showUpload' => false
                                        ]
                                    ]);  
                                ?>
                            </div>
                            
                            <div class="col-sm-10">
                                <?= $form->field($model_exp, "[{$i}]inc_per_year")->textInput() ?>
                            </div>
                            
                            <div class="col-sm-10">
                                <?= $form->field($model_exp, "[{$i}]inc_per_year_file")->textInput() ?>
                            </div>
                        </div><!-- .row -->
                    </div>
                </div>
            <?php endforeach; ?>
            </div>
        </div>
    </div><!-- .panel -->
    <?php DynamicFormWidget::end(); ?>
</div>`

danryray avatar Jul 24 '17 16:07 danryray

@danryray change

echo $form->field($model_exp, '[{$i}]prod_per_year_file')->widget(FileInput::classname(), [

to echo $form->field($model_exp, "[{$i}]prod_per_year_file")->widget(FileInput::classname(), [

crash2k avatar Aug 17 '17 12:08 crash2k

@wbraganca How to clean FileInput after form clone? when i upload image for first dynamicForm and click "add" for clone form fields, FileInput not working check your example: https://wbraganca.com/yii2extensions/dynamicform-demo2/index

EDIT: Ok you have bug in

             if (identifiers.length > 1) {
                    var widgetsOptions = [];
                    $elem.parents('div[data-dynamicform]').each(function(i){
                        widgetsOptions[i] = eval($(this).attr('data-dynamicform'));
                    });
                    widgetsOptions = widgetsOptions.reverse();
                    for (var i = identifiers.length - 1; i >= 1; i--) {
                        identifiers[i] = $elem.closest(widgetsOptions[i].widgetItem).index();
                    }
                }

each has zero-based numbering and for me widgetsOptions have only single element widgetsOptions[0], i = identifiers.length for me is 2 and: $elem.closest(widgetsOptions[i].widgetItem).index(); is trying to get widgetsOptions[1]

crash2k avatar Aug 17 '17 12:08 crash2k

I am working on updating the multiple images, but I have an error with the images when executing this action, it updates only the new images that were loaded in this action, the previous ones that were already loaded are deleted. The text data is fine, the detail is with the images

My form:

                                               <?= $form->field($modelCaractbox, "[{$i}]imgthumb")->label(false)->widget(FileInput::classname(), [ 'options' => [
                                                    'multiple' => false,
                                                    'accept' => 'image/*',
                                                    'class' => 'caractboxes-img'
                                                ],
                                                'pluginOptions' => [
                                                    'previewFileType' => 'image',
                                                    'showCaption' => false,
                                                    'showUpload' => false,
                                                    'browseClass' => 'btn btn-default btn-sm',
                                                    'browseLabel' => ' Pick image',
                                                    'browseIcon' => '<i class="glyphicon glyphicon-picture"></i>',
                                                    'removeClass' => 'btn btn-danger btn-sm',
                                                    'removeLabel' => ' Delete',
                                                    'removeIcon' => '<i class="fa fa-trash"></i>',
                                                    'previewSettings' => [
                                                        'image' => ['width' => '138px', 'height' => 'auto']
                                                    ],
                                                    'initialPreview' => $initialPreview,
                                                    'layoutTemplates' => ['footer' => '']
                                                ]
                                            ]) ?>

My controller

public function actionUpdatedynamic($id)
{
    $this->layout = 'dashboardLayout';
    $model = $this->findModel($id);
    $modelsCaractbox = $model->caractboxes;

    if ($model->load(Yii::$app->request->post())) {

        $oldIDs = ArrayHelper::map($modelsCaractbox, 'id', 'id');
        $modelsCaractbox = Model::createMultiple(Caractbox::classname(), $modelsCaractbox);

        Model::loadMultiple($modelsCaractbox, Yii::$app->request->post());
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsCaractbox, 'id', 'id')));
        $uploadDir =Yii::getAlias('@web') . "upload/images/";

        foreach ($modelsCaractbox as $i => $modelCaractbox) {
            $file[$i] = \yii\web\UploadedFile::getInstance($modelCaractbox, "[{$i}]imgthumb");
            $path[$i] = $uploadDir.$file[$i];
            if ($file[$i]) {
                $modelCaractbox->imgthumb = $path[$i];
                $file[$i]->saveAs($uploadDir.$file[$i]);
            }
        }

        // ajax validation
        if (Yii::$app->request->isAjax) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ArrayHelper::merge(
                ActiveForm::validateMultiple($modelsCaractbox),
                ActiveForm::validate($model)
            );
        }

        // validate all models
        $valid = $model->validate();
        $valid = Model::validateMultiple($modelsCaractbox) && $valid;
        if ($valid) {
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                if ($flag = $model->save(false)) {
                    if (!empty($deletedIDs)) {
                        Caractbox::deleteAll(['id' => $deletedIDs]);
                    }
                    if ($flag) {
                    foreach ($modelsCaractbox as $modelCaractbox) {
                        if ($modelCaractbox->isNewRecord) :
                            $modelCaractbox->fecha =  date("Y-m-d H:i:s");
                            $modelCaractbox->fkuser = Yii::$app->user->identity->id;
                        endif;
                        $modelCaractbox->fkcaract = $model->id;
                        $modelCaractbox->fkproducto = $model->fkproducto;

                        if (!($flag = $modelCaractbox->save(false))) {
                            $transaction->rollBack();
                            break;
                        } 
                    }
                }
            }
                if ($flag) {
                    $transaction->commit();
                    return $this->redirect(['viewdynamic', 'id' => $model->id]);
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        }
    
    }

    return $this->render('updatedynamic', [
        'model' => $model,
        'modelsCaractbox' => (empty($modelsCaractbox)) ? [new Caractbox] : $modelsCaractbox,
        'id' => $id,
    ]);
}
                                    

Please ¡Helpme!!

JuamVizard avatar Jun 12 '19 16:06 JuamVizard

This problem appears because kartik file input adding ID attribute to file preview frame. I solved this by code in view file:

$js = <<<JS
$(".add-variant").click(function() {
  $(".file-preview-frame").removeAttr("id");
})
JS;

$this->registerJs($js);

It's work for me.

Redleks avatar Sep 20 '20 19:09 Redleks