wbraganca / yii2-dynamicform

It is widget to yii2 framework to clone form elements in a nested manner, maintaining accessibility.
Other
436 stars 439 forks source link

Does not work for image uploads #33

Open uthpalax opened 9 years ago

uthpalax commented 9 years ago

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

wbraganca commented 9 years ago

How is the code in your view file?

uthpalax commented 9 years ago

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

<?php $form = ActiveForm::begin([ 'options'=>['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' => '', ] ] ]); ?>

field($model, 'title')->textInput(['maxlength' => 100]) ?>
field($model, 'district')->textInput(['maxlength' => 50]) ?>
field($model, 'area')->textInput(['maxlength' => 50]) ?>
<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 commented 9 years ago

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

wbraganca commented 9 years ago

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

uthpalax commented 9 years ago

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 commented 9 years ago

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

jgrasta commented 9 years ago

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

maheshtc commented 9 years ago

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

wbraganca commented 9 years ago

@maheshtc Could you post here your view code?

maheshtc commented 9 years ago

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

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

Story Images

```
'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', ], ]); ?>
1 && $model->$filename && $model->$file_desc):?>
field($model, $file_desc)->textInput(['maxlength' => true]) ?> field($model,$filename)->widget(FileInput::className(),[ 'pluginOptions' => ['previewFileType' => 'image','showUpload'=>false,'browseLabel' => '', 'removeLabel' => '', 'mainClass' => 'input-group-lg'], 'options'=>['accept' => 'image/*'], ]);?>
maheshtc commented 9 years ago

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

wbraganca commented 9 years ago

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'
    ]
]) ?>
maheshtc commented 9 years ago

@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.

ghost commented 9 years ago

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

maheshtc commented 9 years ago

@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

cratemos666 commented 9 years ago

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)

bookin commented 9 years ago

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

invisor commented 8 years ago

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

pliszka commented 8 years ago

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.

ryanmakinano commented 7 years ago

please provide working for dynamic form file upload please

ryanmakinano commented 7 years ago

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

danryray commented 7 years ago

@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.

`<?php $form = ActiveForm::begin(['id' => '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' ], ]); ?>

Experiences

$model_exp): ?>

Detail

isNewRecord) { echo Html::activeHiddenInput($model_exp, "[{$i}]id"); } ?>
field($model_exp, "[{$i}]start_year")->textInput(); ?>
field($model_exp, "[{$i}]end_year")->textInput(); ?>
field($model_exp, "[{$i}]company")->textInput(); ?>
field($model_exp, "[{$i}]prod_per_year")->textInput() ?>
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 ] ]); ?>
field($model_exp, "[{$i}]inc_per_year")->textInput() ?>
field($model_exp, "[{$i}]inc_per_year_file")->textInput() ?>
`
crash2k commented 7 years ago

@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 commented 7 years ago

@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]

JuamVizard commented 5 years ago

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!!

Redleks commented 4 years ago

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.