1
votes

I created a form with ActiveForm which include one multiple file input. I enabled AJAX validation on submit but when I select "n" items and click the submit button, yii send data in background but the file validator return the next error message: "Please upload a files". Ok I understand that why do it but I don't know that what the best practise if I want to check max file numbers and sizes and required at least one file and I want to use ajax validation too. Perhaps the best practise if I don't use ajax validation and I change the skipOnEmpty from false to true...?

Example (not the real full code):

Model:

class Document extends Model {
    public $name;
    public $files;

    public function rules()
    {
        return [
            ['name', 'required'],
            ['files', 'file',
                'maxSize'     => 1024 * 1024,
                'maxFiles'    => 5,
                'skipOnEmpty' => false
            ]
        ];
    }

    public function create() { // other code }
}

Controller:

class DocumentController extends Model
{
    public function create()
    {
        $model = new Document();

        $model->load(Yii::$app->request->post());
        $model->files = UploadedFile::getInstances($model, 'files');

        if (Yii::$app->request->isAjax) {
            Yii::$app->response->format = Response::FORMAT_JSON;

            return ActiveForm::validate($model);
        }

        if ($model->validate() && $model->create()) {
           // other code...
        }
    }
}

Thx guys!

3
Why does you Controller extends Model? - Nebulosar
it was just an erratum in the example. - szaboolcs
It's confusing, you should make valid examples so that people can help you better :) - Nebulosar
Have you never maked a mistake? I think you should write a helpful answer :) - szaboolcs
Haha, if I could, I would.. :D - Nebulosar

3 Answers

1
votes

That's known issue: https://github.com/yiisoft/yii2/issues/6873

You can make widget which validate your upload on client side and if all right send files to server where they will be validated again with your model and return error if something wrong.

Widget example https://github.com/2amigos/yii2-file-upload-widget

0
votes

#controller ajax validation same as expect

if ($model->load(Yii::$app->request->post())) {
    if (Yii::$app->request->isAjax) {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        return ActiveForm::validate($model);
    }
}

#model validation with fileRequired scenario

['filePath', 'required', 'on' => ['fileRequired']],

$tempScenario = $documentModel->scenario;

$documentModel->scenario = 'fileRequired';

echo $form->field($documentModel, "filePath", [
    'enableClientValidation' => true,
    'enableAjaxValidation' => false,
])->fileInput();
$documentModel->scenario = $tempScenario;

A enableAjaxValidation remove for ajax validation and enableClientValidation is for client validation which work perfectly for file validation

-1
votes

//model

public function rules()
{
    return [

        [['identity_copy','home_copy', 'certificate_copy'], 'file', 
            'skipOnEmpty' => false,'on' => 'imageFalse',
            'extensions' => 'jpg, png, gif',
            'wrongExtension' => '{attribute} ควรเป็น {extensions} เท่านั้น.',
            'maxSize' => 512000,
        ],
        [['identity_copy','home_copy', 'certificate_copy'], 'file', 
            'skipOnEmpty' => TRUE,'on' => 'imageTrue',
            'extensions' => 'jpg, png, gif',
        ],
    ];
}

//controller

public function actionCreate() {

    $model = new StdRecord();

    $model->scenario = 'imageFalse';

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

        $model->scenario = 'imageTrue';


        $model->save();
        Yii::$app->session->setFlash('success', 'บันทึกข้อมูลเรียบร้อย');
        return $this->redirect(['view', 'id' => $model->std_id]);
    } else {
        if(Yii::$app->request->isAjax){
           return $this->renderAjax('create', [
               'model' => $model,
        ]);  
        } else {
            return $this->render('create', [
              'model' => $model,
        ]);  
        }
    }
}