Пользовательская проверка не работает — Yii2-app-basic-Yii2

Вчера я опубликовал один вопрос относительно пользовательской проверки для переключателя Textfield Mandatory On Радиокнопка. Я получил ответ. Но это был не точный ответ. Но это решило одну мою проблему.

На самом деле, у меня есть 2 радиокнопки.

  • Индивидуальный
  • Твердый

Когда выбрана радиокнопка со значением «Индивидуальное», текстовое поле CompanyName не должно быть обязательным. Но когда выбрана радиокнопка со значением «Фирма», текстовое поле CompanyName должно быть обязательным.

Теперь происходит следующее: когда я выбираю переключатель «Фирма» и не заполняю какое-либо значение для текстового поля CompanyName, данные не вставляются в таблицу базы данных. ОТЛИЧНО. Это нормально. Но сообщение об ошибке не отображается в форме. Сообщение об ошибке должно отображаться, поскольку текстовое поле CompanyName является обязательным после выбора фирмы Radio Button.

Я не понимаю, где я делаю ошибку. Вот мой вид, контроллер и код модели. Пожалуйста, помогите мне.

register.php (ПРОСМОТР)

<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\captcha\Captcha;
use yii\bootstrap\Modal;
use yii\helpers\Url;
?>

<?php $form = ActiveForm::begin(['id' => 'register-form']); ?>
    .
    .
    .
    <?= $form->field($model, 'AdminType')
            ->radioList(array('Individual'=>'An Individual', 'Firm'=>'Firm/Company'))
            ->label('Are You')?>
    <?= $form->field($model, 'CompanyName')->textInput()->label('Company Name')->error() ?>
    .
    .
<?php ActiveForm::end(); ?>

SiteController.php (КОНТРОЛЛЕР)

<?php

namespace app\controllers;

use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\swiftmailer\Mailer;
use app\models\RegisterForm;

public function actionRegister()
{
    // Register Model
    $model = new RegisterForm();
    if ($model->load(Yii::$app->request->post())) 
    {
        $post = Yii::$app->request->post('RegisterForm');
        if ($model->validate())
        {

        }
        else
        {
            // HERE YOU CAN PRINT THE ERRORS OF MODEL
            echo "<pre>";
            print_r($model->getErrors());
            echo "</pre>";
        }
        return $this->refresh();
    }

}

RegisterForm.php (МОДЕЛЬ)

<?php

namespace app\models;

use Yii;
use yii\base\Model;
use kartik\password\StrengthValidator;


class RegisterForm extends Model
{
    public $fname;
    public $lname;
    public $email;
    public $password;
    public $confirmPassword;
    public $AdminType;
    public $CompanyName;
    public $verifyCode;

    public function rules()
    {
        return [
                [['fname','lname', 'email', 'password','confirmPassword','verifyCode','AdminType'], 'required'],
                ['email', 'email'],
            ['confirmPassword', 'compare', 'compareAttribute' => 'password'], 
                ['verifyCode', 'captcha'],

        //add rule that uses the validator function
                ['AdminType','radioValidator'],
        ];
    }

    //implement the validator
    public function radioValidator($attribute)
    {
        if($this->$attribute === 'Firm')
            return $this->addError('CompanyName', 'Company Name cannot be blank');
    }
}

person Nana Partykar    schedule 06.10.2015    source источник
comment
Проверяете ли вы регистрационную форму? $model->validate()   -  person Sergey    schedule 06.10.2015
comment
Ооо.. Извините, мистер @Sergey. Я не включил сюда. да Но @model-›validate() присутствует в моем контроллере. Я только что отредактировал свой вопрос.   -  person Nana Partykar    schedule 06.10.2015
comment
Когда вы вызываете шаблон render в Controller, вы можете не показывать полный класс контроллера - только один метод   -  person Sergey    schedule 07.10.2015


Ответы (5)


Вы должны добавить 'enableAjaxValidation' => true в ActiveForm.

После этого ваш код должен быть,

контроллер

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

    if ($model->load(Yii::$app->request->post())) 
    {
    }
    else
    {
        // HERE YOU CAN PRINT THE ERRORS OF MODEL
        echo "<pre>";
        print_r($model->getErrors());
        echo "</pre>";
    }
    return $this->refresh();
}

Просмотреть

<?php $form = ActiveForm::begin([
           'id' => 'register-form',
           'enableAjaxValidation' => true,
]); ?>
    .
    .
    .
    <?= $form->field($model, 'AdminType')
            ->radioList(array('Individual'=>'An Individual', 'Firm'=>'Firm/Company'))
            ->label('Are You')?>
    <?= $form->field($model, 'CompanyName')->textInput()->label('Company Name')->error() ?>
    .
    .
<?php ActiveForm::end(); ?>

Это может помочь вам.

person GAMITG    schedule 06.10.2015
comment
Ok. Позвольте мне проверить мистера @gamitg. - person Nana Partykar; 06.10.2015
comment
После редактирования моего кода, что вы сказали, мистер @gamitg. Теперь форма не отправляется. Значит, теперь кнопка отправки работает как обычная кнопка. Нет, подавая какую-либо вещь. - person Nana Partykar; 06.10.2015
comment
см. ошибку в консоли firebug. какая ошибка возникает? - person GAMITG; 06.10.2015
comment
Ошибка отображается сейчас после выбора FIRM. Но капча показывает неверный код подтверждения. И после этого я ничего не трогал. И, еще одно, форма не отправляется даже после выбора переключателя INDIVIDUAL. Думаю из-за капчи. - person Nana Partykar; 06.10.2015
comment
Я думаю, вы близки к тому, чтобы ответить мистеру @gamitg. Ваш работает, но из-за этого капча не работает. - person Nana Partykar; 06.10.2015
comment
НИКОГДА не используйте капчу с enableAjaxValidation = true, потому что, если у вас включена проверка ajax, она отправляет сообщение контроллеру и проверяет его. Если у вас есть, например. несколько полей ввода и делать сообщение ajax для каждого события размытия, тогда вы должны создать новую капчу на стороне контроллера после достижения testLimit (по умолчанию 3), поэтому после 3 запросов ajax у вас будет другая капча на стороне сервера, отмеченная как действительно, и поэтому ваша отправка всегда будет терпеть неудачу! - person BHoft; 06.10.2015
comment
Источник: Note that once CAPTCHA validation succeeds, a new CAPTCHA will be generated automatically. As a result, CAPTCHA validation should not be used in AJAX validation mode because it may fail the validation even if a user enters the same code as shown in the CAPTCHA image which is actually different from the latest CAPTCHA code. yiiframework.com/doc-2.0/yii-captcha-captchavalidator. .html - person BHoft; 06.10.2015
comment
Тогда как отключить ajaxValidation только для капчи Mr @BHoft? - person Nana Partykar; 06.10.2015
comment
см. мой ответ (потому что необходимо добавить код, что невозможно в комментариях) - person BHoft; 07.10.2015

Atlast, я получил свой ответ

     //company_name
      ['company_name', 'required', 'when' => function($model){
        return ($model->user_type == 'Firm' ? true : false);
      }, 'whenClient' => "function (attribute, value) {
          return $('input[type=\"radio\"][name=\"Users[user_type]\"]:checked').val() == 'Firm';
      }"],
person Nana Partykar    schedule 15.10.2015

@Нана Патикар

Как вы спросили, как можно отключить проверку ajax для капчи, я попробовал этот способ. Но я не уверен, что это правильный путь.

Я установил форму с этими настройками

'enableAjaxValidation' => true,
'enableClientValidation' => false,
'validateOnSubmit' => false,

и изменил проверку действия на это (я удалил свою капчу в моем случае «verifyCode» из атрибутов, которые должны быть проверены.

if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
        Yii::$app->response->format = 'json';
        $validateAttributes = $model->activeAttributes();
        $key = array_search('verifyCode', $validateAttributes);
        if ($key!==false) {
            array_splice($validateAttributes, $key, 1);
        }
        return \yii\widgets\ActiveForm::validate($model, $validateAttributes);
}
person BHoft    schedule 07.10.2015

На самом деле, ваш метод действий неверен. Когда вы вызываете refresh(), вы в основном перезагружаете страницу. Если модель не обновлялась в базе данных, вы не увидите ничего особенного и никаких ошибок, так как перезагрузите свежую модель.

Этот код будет отображать ошибку, как обычно, в вашем представлении:

   /**
     * @return \yii\web\Response
     */
    public function actionRegister()
    {
        // Register Model
        $model = new RegisterForm();
        if ($model->load(Yii::$app->request->post()))
        {
            $post = Yii::$app->request->post('RegisterForm');
            if ($model->validate())
            {
                 // whatever
            }

//            return $this->refresh(); // do not refresh but...
        }

        // ... render the view with the current model, who's errors attribute is filled
        return $this->render('register', compact('model'));
    }

NB: также вам не нужно вызывать error() в своем представлении, метод рендеринга ActiveFormField позаботится об этом за вас:

<?= $form->field($model, 'CompanyName')->textInput()->label('Company Name') ?>

достаточно

person ChristopheBrun    schedule 07.10.2015

Если вы вызываете error без опций, вы подавляете вывод ошибок

Метод ActiveField error

yii\widgets\ActiveField

public function error($options = [])
{
    if ($options === false) {
        $this->parts['{error}'] = '';
        return $this;
    }
    $options = array_merge($this->errorOptions, $options);
    $this->parts['{error}'] = Html::error($this->model, $this->attribute, $options);

    return $this;
}

Вам нужно удалить метод call error в VIEW

<?= $form->field($model, 'CompanyName')->label('Company Name')->textInput() ?>
person Sergey    schedule 06.10.2015
comment
@NanaPartykar, я нашел твою ошибку - я бы обновил свой ответ - person Sergey; 07.10.2015