Загрузка файла Yii2 pjax для использования в ActiveForm

Я создаю активную форму Yii2 для создания и редактирования продукта и хочу, чтобы страница также управляла изображениями. Я хочу иметь возможность загружать (добавлять) изображения для продукта, а затем иметь сортируемую область предварительного просмотра, где изображения отображаются и могут быть отсортированы в правильном порядке. Мой план состоит в том, чтобы загружать файлы через ajax/pjax во временную папку, из которой будет извлекаться форма, чтобы отображать их в сортируемой области, и после сохранения модели изображения будут перемещены/имены соответственно.

Сначала я использую виджет Kartik FileInput (который может быть ненужным) и Сортируемый ввод Kartik для изменения порядка изображений.

Я считаю, что могу справиться с загрузкой и перемещением/переименованием файлов, мой вопрос заключается в том, как загрузить изображения отдельно от остальной части формы, а затем заставить ActiveForm вытащить их в сортируемую область ввода? Кроме того, я также хочу иметь возможность удалять из него изображения (с маленьким крестиком в углу миниатюры). Я знаком с использованием pjax для обертывания представлений сетки и даже с использованием pjax для отправки формы методу pjax (для использования внутри модального режима), но не уверен, как использовать его внутри другой формы и заставить другую форму динамически загружать картинки.

Чтобы уточнить, у меня есть Product, который расширяет ActiveRecord, и ImageForm, который расширяет Model. Затем у меня есть ProductController со следующим действием Create:

public function actionCreate()
{
    $model = new Product();
    $images = new ImageForm();

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

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

Моя цель состоит в том, чтобы иметь возможность загружать изображения (через ImageForm) во временное расположение, которое отображается в представлении create Продукта. Однако в настоящее время использование функции загрузки в виджете просто перезагружает страницу, и изображения исчезают.


person sharf    schedule 03.02.2018    source источник
comment
хорошо, вы можете использовать formModel, который расширяет yii\base\Model, чтобы загрузить файл с помощью kartik\FileInput. Я не вижу никаких проблем в том, что ваша обычная форма будет иметь отдельную модель, которая расширена от \yii\db\ActiveRecord, вы можете использовать события, предоставляемые виджетом FileInput, для обновления div в котором вы хотите показывать загруженные файлы или сделать отдельный action в вашем controller который вызывается этим event с помощью ajax   -  person Muhammad Omer Aslam    schedule 03.02.2018
comment
@MuhammadOmerAslam, есть ли способ «yii» сделать этот вызов ajax, или я просто пишу javascript для обнаружения события? Кроме того, как мне отправить только форму загрузки, а не всю форму продукта?   -  person sharf    schedule 04.02.2018
comment
если вы используете kartik\FileInput, вам не нужно писать javascript для публикации изображения, у него есть возможность инициировать загрузку, как только вы выберете файл, и поскольку он использует ActiveForm и model, так что да, это yii способ загрузки, он будет даже показать вам проверку модели, если она не удалась. нравится, если ограничение размера увеличивается   -  person Muhammad Omer Aslam    schedule 04.02.2018
comment
@MuhammadOmerAslam извините за мое невежество, я использую fileInput в сценарии $form->field()->widget, нужно ли мне встраивать еще одну активную форму в первую, чтобы это сработало? И как только загрузка будет завершена, как я могу запустить обновление? Это пользовательский javascript или есть способ запустить его иначе? Я собираюсь немного поработать над этим и обновить свой вопрос по мере необходимости.   -  person sharf    schedule 04.02.2018
comment
используемый вами FileInput должен использовать тот же ActiveForm, но другой объект модели, который будет принадлежать вашему классу UploadForm, то есть $form->field('imagefileName',$uploadModel)->widget()   -  person Muhammad Omer Aslam    schedule 04.02.2018
comment
@MuhammadOmerAslam Вот где ты меня потерял. У меня есть $model, представляющий продукт (ActiveRecord), и $images, представляющий форму изображения (модель), и когда я нажимаю кнопку загрузки на виджете, форма отправляется (или завершается ошибкой проверки в других полях), и страница обновляется с моим вводите данные, поле загрузки чистое, а изображения никуда не загружались.   -  person sharf    schedule 04.02.2018
comment
вы должны использовать опцию загрузки ajax и указать uploadUrl для fileInput, чтобы он не отправлял вашу форму   -  person Muhammad Omer Aslam    schedule 04.02.2018
comment
@MuhammadOmerAslam Я не знал о uploadUrl, чтобы сделать его ajax, спасибо за это. Я установил его, и он правильно подходит к моему методу, однако данные публикации содержат только значение file_id, и я до сих пор не понимаю, как это вызовет обновление родительской формы и получение изображений после их обработки.   -  person sharf    schedule 04.02.2018
comment
см. ответ, я добавил надежду, которая поможет вам   -  person Muhammad Omer Aslam    schedule 06.02.2018


Ответы (1)


Вы можете использовать отдельную модель для загрузки изображения и использовать ту же форму, просто передав объект модели $uploadForm для заполнения поля формы для file, вы можете использовать виджет kartik\FileInput, который имеет возможность загружать файл через ajax через uploadUrl, вы может инициировать загрузку при выборе файла автоматически с помощью события fileUploaded, и после загрузки у вас есть 2 варианта: либо вы используете uploadAsync=>true и используйте filebatchuploadsuccess, который срабатывает после загрузки всех файлов, или использовать настройки по умолчанию и использовать filebatchuploadcomplete, который срабатывает после каждой загрузки файла. Оба этих события предоставляют список загруженных файлов, но будьте осторожны, так как вы проверяете файлы после их отправки, вы должны вернуть ответ в случае ошибки, чтобы пользователь был уведомлен о файлах, которые не были загружены, вы можете либо список файлов, предоставленный событиями, либо лучше использовать отдельный action внутри вашего контроллера и вызвать его внутри функции относительного успеха, которую вы используете, с помощью вызова ajax и заполнить список загруженных файлов, если вы сохраняете их внутри запроса таблицы таблица для отображения имен

fileselect : это событие запускается после файлы выбираются при вводе файлов с помощью кнопки просмотра файлов. Это немного отличается от события изменения в том смысле, что оно будет запущено, даже если диалоговое окно просмотра файлов будет отменено.

Как вы собираетесь его использовать

//get filinput object
var $input=$("#input-id");

 $input.on('fileselect', function(event, numFiles, label) {

    //trigger file upload with 1 sec delay
    setTimeout(function() {
    $input.fileinput("upload");
}, 1000);
});

filebatchuploadcomplete: это событие запускается только для загрузки ajax и после завершения либо синхронной, либо асинхронной пакетной загрузки ajax.

Доступны дополнительные параметры:

  • files: массив стека файлов (или пустой объект, если он недоступен).

  • extra: настройки uploadExtraData для плагина (или пустой объект, если он недоступен).

Образец кода

$('#input-id').on('filebatchuploadcomplete', function(event, files, extra) {
    //call the ajax function here to query the files that are uploaded
});
person Muhammad Omer Aslam    schedule 04.02.2018
comment
Я не пошел с этим точным ответом, но это привело меня к решению. Я использовал первый бит JS для автоматической отправки формы (не обязательно с кнопкой загрузки, предоставленной плагином, но мне нравится это прикосновение), затем я обернул activeForm в pjax, а затем в событии filebatchuploadcomplete перезагрузил pjax, поэтому я могу использовать контроллер для более прямого управления. - person sharf; 07.02.2018
comment
да, можно и так, если вас это устраивает. это сработает, рад, что вы смогли решить эту проблему @shalf - person Muhammad Omer Aslam; 07.02.2018