Задать вопрос
alexanderbulatov
@alexanderbulatov
Fullstack разработчик

Как правильно добавить в существующую форму новый FileInput от Kartik в ActiveForm Yii2?

Доброго времени суток!

Задача такова, что нужно добавить новое поле FileInput от Kartik-а в форму, которая создана ActiveForm и уже отрендерена.

У меня сделано это следующим образом.

Экшен в контроллере:
public function actionCreate()
    {
        $model = new Slider();
        $uploadingForm = new UploadingForm();

        if ($model->load(Yii::$app->request->post()) && $model->save()) { 
            $this->saveImages($model, $uploadingForm);                   
            return $this->redirect(['view', 'id' => $model->id]);
        }

        return $this->render('_form', [
            'model' => $model,
            'uploadingForm' => $uploadingForm,
        ]);
    }


View:
<?php

use yii\helpers\Html;
use yii\bootstrap4\ActiveForm;
use kartik\file\FileInput;
use yii\helpers\Url;

/* @var $this yii\web\View */
/* @var $model app\models\Slider */
/* @var $form yii\bootstrap4\ActiveForm */
/* @var $uploadingForm app\models\UploadingForm */
/* @var $collectionFileArray this is a collection of a current slider represented as an array of paths  */
?>
<div class="slider-form">

    <?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, 'where')->dropDownList(
        $model::associatedArrayOfLocations()
    ) ?>

    <?= $form->field($model, 'status')->radioList([
        $model::STATUS_OFF => 'Выключен',
        $model::STATUS_ON => 'Включён',
    ], [
        'item' => function($index, $label, $name, $checked, $value) {
            $item = Html::beginTag('div', ['class' => 'custom-control custom-radio']);
            $item .= Html::radio($name, $checked, ['id' => 'article-status-'.$index, 'value' => $value, 'class' => 'custom-control-input']);
            $item .= Html::label($label, 'article-status-'.$index, ['class' => 'custom-control-label']);
            $item .= Html::endTag('div');
            return $item;
        },
    ])->hint('По умолчанию "Включен"') ?>

    <?= $form->field($uploadingForm, 'imageFiles[]')->widget(FileInput::class, [
        'options' => ['id' => 'foo', 'accept' => 'image/*'],
        'pluginOptions' => [
            'initialPreview' => $collectionFileArray ?? '',
            'initialPreviewAsData' => true,
            'fileActionSettings' => [
                'showZoom' => false,
                'showRemove' => false,
            ],
            'showCaption' => true, // show an input where we show the name of an uploading file
            'showRemove' => false,
            'showUpload' => false,
            'showCancel' => false, // show a cancel of uploading process button
            'browseClass' => 'btn btn-primary',
            'browseLabel' => 'Загрузить',
            //'maxFileSize' => 15000,
        ],
    ]) ?>

    <?= $form->field($uploadingForm, 'imageFiles[]')->widget(FileInput::class, [
        'options' => ['id' => 'bar', 'accept' => 'image/*'],
        'pluginOptions' => [
            'initialPreview' => $collectionFileArray ?? '',
            'initialPreviewAsData' => true,
            'fileActionSettings' => [
                'showZoom' => false,
                'showRemove' => false,
            ],
            'showCaption' => true, // show an input where we show the name of an uploading file
            'showRemove' => false,
            'showUpload' => false,
            'showCancel' => false, // show a cancel of uploading process button
            'browseClass' => 'btn btn-primary',
            'browseLabel' => 'Загрузить',
            //'maxFileSize' => 15000,
        ],
    ]) ?>

    <?= Html::button('add', [
        'class' => 'btn btn-primary', 'id' => 'add-input',
        'data-url' => Url::to(['/admin/slider/add-input'])
    ]) ?>
    <?php $this->registerJs("
        $('#add-input').on('click', function() {
            let self = this;
            $.ajax($(self).data('url'), {
                method: 'post',
                processData : false,
                contentType : false,
                success: function(r) {
                    $(self).before(r);
                },
            });
        });
    "); ?>

    <div class="form-group">
        <?= Html::submitButton('Сохранить', ['class' => 'btn btn-block btn-success']) ?>
    </div>

    <?php ActiveForm::end(); ?>

</div>


Экшен для добавления нового поля через Ajax:
public function actionAddInput()
    {
        return $this->renderAjax('_ajax-slide');
    }


View _ajax-slide:
<?php

use yii\bootstrap4\ActiveForm;
use kartik\file\FileInput;
use app\models\forms\UploadingForm;


$form = new ActiveForm();
$model = new UploadingForm();
?>

<?= $form->field($model, 'imageFiles[]')->widget(FileInput::class, [
    'options' => ['id' => 'new-input', 'accept' => 'image/*'],
    'pluginOptions' => [
        'initialPreview' => false,
        'initialPreviewAsData' => true,
        'fileActionSettings' => [
            'showZoom' => false,
            'showRemove' => false,
        ],
        'showCaption' => true, // show an input where we show the name of an uploading file
        'showRemove' => false,
        'showUpload' => false,
        'showCancel' => false, // show a cancel of uploading process button
        'browseClass' => 'btn btn-primary',
        'browseLabel' => 'Загрузить',
        //'maxFileSize' => 15000,
    ],
]); ?>


Поле действительно по клику на кнопку добавляется, но оно не отображается. При этом появляется крошечный квадратик и можно кликнуть по нему и на самом деле загрузить изображение, но сам виджет FileInput не показывается.

При этом в консоли браузера показывается ошибка:
Uncaught ReferenceError: fileinput_0c236089 is not defined


Я понимаю так, что FileInput при рендеринге страницы создаёт некий уникальный идентификатор страницы (я так подумал, так как все другие FileInput виджеты, если их добавить, будут иметь один номер). Вот вопрос, как добавить этот номер к своему новому полю, чтобы виджет отобразил поле?

И вообще, как его как бы обновить что ли? Переинициализировать? Тогда как?

Буду благодарен за любую идею как решить. В общем задача динамически добавлять и удалять этот виджет FileInput, при чём в любых количествах на текущей странице.
  • Вопрос задан
  • 375 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы