Yii2 ActiveForm radioList required value verification - yii2

I implented a form using the Yii2 activeForm field, but can't get the form to submit. I keep getting the verification error "Payment Method cannot be blank" from the model, I set the payment method as a required value, but somehow the value from the radioList doesn't get to the model's payment_method attribute.
Model:
class OrderFormModel extends Model
{
public $total;
public $extra;
public $admin_message;
public $is_taxed;
public $alt_email;
public $payment_method;
public $alt_address;
public $address;
public $attachment;
public $lat;
public $lon;
const PAY_CREDIT = 1;
const PAY_CHEQUE = 2;
public static function getPaymentMethods()
{
return[
self::PAY_CREDIT => 'Pay Via Credit Card',
self::PAY_CHEQUE => 'Pay Via Cheque / Interac'
];
}
public function rules()
{
return
[
[['total', 'extra'], 'number'],
[['admin_message'], 'string', 'max' => 1000],
[['is_taxed'], 'integer'],
['alt_email', 'email'],
[['payment_method'], 'integer'],
[['payment_method'], 'required'],
[['alt_address'], 'string', 'max' => 255],
['address', 'validateAddress','skipOnEmpty' => false, 'skipOnError' => false],
[['attachment'], 'file', 'extensions' => 'pdf, doc, docx, rtf, txt'],
[['lat','lon'], 'double']
];
}
}
View:
<div id="payment_method" style="margin-bottom: 5%">
<h2 style="text-align: center">Set Customer Payment Option</h2>
<div class="row">
<?= $form->field($orderForm,'payment_method')->radioList(OrderFormModel::getPaymentMethods(),
["class"=>"form-control", "id"=>"pymnt-method", "tag" => "false","required" => "true","onclick"=>"$('#orderDetails-payment_method').val( $('input:radio:checked').val() )",
"itemOptions" => ["class" => "radio"],
"item" => function($index, $label, $name, $checked, $value){
$return = '<div class="col-sm-6"><label class = "modal-radio">';
$return .= '<input type = "radio" name ="'. $name .'" value = "' . $value .'" tabindex = "3" >';
$return .= '<span style = "padding: 0.7em;"><b style="font-size: 1.8em;">' . ucwords($label) .'</b></span>';
$return .= '</label></div>';
return $return;
}]) ?>
</div>
</div>

Related

Validate checked checkbox quantity

I have a voting form and I would like to validate the minimum and maximum number of candidates that each voter can vote for. These max and min values are stored in the logged user's session. What better way to do it?
MODEL Voto.php
public static function tableName()
{
return 'voto';
}
public function rules()
{
return [
[['eleicao_id', 'candidato_id', 'cargo_id', 'urna_id', 'created'], 'required','message'=> 'Selecione no mínimo 1 candidato!'],
[['eleicao_id', 'cargo_id', 'urna_id'], 'integer'],
[['created','candidato_id'], 'safe'],
[['eleitor_hash'], 'string', 'max' => 255],
];
}
FORM _form_votacao.php
<?php $form = ActiveForm::begin(); ?>
<div class="row">
<?php
$candidato = ArrayHelper::map(candidato::find()
->where(['status' => 1])
->Andwhere(['eleicao_id' => Yii::$app->user->identity->eleicao_id])
->orderBy("nome ASC")
->all(), 'id', 'nome'
);
echo $form->field($model, 'candidato_id')->checkboxList($candidato, [
'class' => 'h4',
'data-toggle' => 'button',
'item' => function($index, $label, $name, $checked, $value) {
return "<label class='col-md-5'><input type='checkbox' {$checked} name='{$name}' value='{$value}'> {$label}</label>";
}])->label(false);
?>
</div>
<br>
<div class="row text-center">
<div class="form-group">
<?= Html::submitButton('Confirmar', ['class' => 'btn btn-success']) ?>
</div>
</div>
<?php ActiveForm::end(); ?>
Note: This list of candidates is dynamic, loads the candidates according to the parameters of the user logged in.
Rules Test UPDATE:
public function rules()
{
return [
['candidato_id', 'validateCandidates','message'=> 'teste'],
];
}
public function validateCandidates($attribute, $params, $validator){
if(count($this->candidato_id) >= 4){ // test with value 4
$this->addError($attribute, 'Error message');
}
}
Create custom validation. Something like this:
Model Voto.php
public function rules()
{
return [
....
['candidato_id', 'validateCandidates'],
....
];
}
public function validateCandidates($attribute, $params, $validator){
if(count($this->candidato_id) < {session_min} and count($this->candidato_id) > {session_max}){
$this->addError($attribute, 'Error message');
}
}

How can I valid random names fields in Yii?

I have a lot of fields generated from loops. I would like to validate them through validation rules (integer). I don't know how to throw so many fields with random names into the model to the rules () function. How can I validate fields without a model?
View:
<?= Html::input('number', 'file[' . $indexRow . ']' . '[' . $indexCell . ']', $cell, $options = ['class' => 'form-control', 'filter' => 'intval', 'integer']) ?>
Controller:
` public function actionEdit($fileName)
{
$siteHelper = new SiteHelper();
$editForm = new EditForm();
$preparedRows = $siteHelper->prepareRows($fileName);
$preparedHTML = '';
if (Yii::$app->request->isPost) {
$post = Yii::$app->request->post();
if (isset($post['file'])) {
$dataFile = $post['file'];
$preparedRows = $siteHelper->updateExcelFile($fileName, $dataFile);
Yii::$app->session->setFlash('success', 'Plik został zaktualizowany!');
} else if (isset($post['EditForm'])) {
$events = $post['EditForm']['events'];
$preparedHTML = $siteHelper->prepareHTML($events, $preparedRows, $fileName);
Yii::$app->session->setFlash('success', 'Wygenerowano plik PDF!');
}
}
$viewParameters = [
'rows' => $preparedRows,
'editForm' => $editForm,
'scoreHTML' => $preparedHTML,
'downloadLink' => Url::toRoute(['site/download', 'fileName' => $fileName])
];
return $this->render('edit', $viewParameters);
}`
Model:
`
class EditForm extends Model
{
public $events;
public function rules()
{
return [
[['events'], 'required'],
['events', 'integer'],
];
}
}`
When you have an array you can use each validator:
https://www.yiiframework.com/doc/api/2.0/yii-validators-eachvalidator
The validation function should be:
public function rules()
{
return [
[['events'], 'each', 'rule' => ['required']],
[['events'], 'each', 'rule' => ['integer']],
];
}
You may need to avoid multidemnsional array in html and render the field like this:
<?= Html::input('number', 'file[' . $indexRow . '-' . $indexCell . ']', $cell, $options = ['class' => 'form-control', 'filter' => 'intval', 'integer']) ?>
later you can "explode" the row cell index (isn't it supposed to be col?) to identify the row and the column.
$rowCellIndecies = explode('-', $rowCellIndex);
explode function: https://www.php.net/manual/en/function.explode.php

Yii2 create or update user profile

In my basic app, I have a User model and a UserForm model that stores and update the users in the database. Now, I got problem when updating the user profile. It feedbacks 'Successful update!' even though the new data won't save.
My table:
Table name: User
Attributes: id, fname, mname, lname, address, username, auth_key, password_hash, password_reset_token, email, status, created_at, updated_at
My Model:
class UserForm extends Model
{
public $fname;
public $mname;
public $lname;
public $address;
public $username;
public $email;
public $password_hash;
/**
* #inheritdoc
*/
public function rules()
{
return [
['fname', 'required'],
['fname', 'trim'],
['mname', 'trim'],
['lname', 'required'],
['lname', 'trim'],
['address', 'required'],
['address', 'trim'],
['address', 'string', 'max' => 255],
['username', 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => '\app\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 4, 'max' => 255],
['email', 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\app\models\User', 'message' => 'This email address has already been taken.'],
['password_hash', 'required', 'on' => 'insert'],
['password_hash', 'string', 'min' => 8],
];
}
public function beforeSave($insert) {
if ($insert) {
$this->setPassword($this->password_hash);
} else {
if (!empty($this->password_hash)) {
$this->setPassword($this->password_hash);
} else {
$this->password_hash = (string) $this->getOldAttribute('password_hash');
}
}
return parent::beforeSave($insert);
}
}
My controller:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->setAttribute('password_hash', null);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->session->setFlash('success', Yii::t('app', 'Successful update!'));
return $this->redirect(['overview']);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
protected function findModel($id) {
if (($model = User::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
My view.php
<?= $form->field($model, 'fname')->textInput(['autofocus' => true])->label('First Name') ?>
<?= $form->field($model, 'mname')->textInput()->label('Middle Name') ?>
<?= $form->field($model, 'lname')->textInput()->label('Last Name') ?>
<?= $form->field($model, 'address')->textInput() ?>
<?= $form->field($model, 'username')->textInput() ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'password_hash')->passwordInput(['placeholder' => Yii::t('app', 'Password'), 'value' => ''])->label(false) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Some of the steps are from here: yii2 user CRUD create or update with password
Your UserForm is never used. Your findModel() returns User, so all validation and saving is handled by User model - I guess it does not have any validation rules, so $model->load() does not load anything.
You may try to extend your form model from active record model:
class UserForm extends User
And use it in findModel() or create separate method for returning form model:
protected function findFormModel($id) {
if (($model = UserForm::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
Then use this method in your update action. Don't forget to remove old properties from UserForm - they're unnecessary and may break attributes behavior.

Yii2 uploadfile image from model method beforeSave

i try to upload 4 or less images, the ajax validation do not return any error, but on submit i get the follow:
"errors": {
"imageFiles": [
"Please upload a file."
]
}
attr:
/**
* #var UploadedFile[]
*/
public $imageFiles;
Rules:
return [
[['imageFiles'], 'required', 'on' => self::REPORT_STEP1],
[['imageFiles'], 'file', 'skipOnEmpty' => false, 'maxFiles' => 4],
];
BeforeSave:
public function beforeSave($insert)
{
$files_urls = [];
$this->imageFiles = UploadedFile::getInstances($this, 'imageFiles');
foreach ($this->imageFiles as $file) {
$path = Url::to(['/uploads/reports/'], true) . Yii::$app->security->generateRandomString() . '.' . $file->extension;
$file->saveAs($path);
$files_urls[] = $file->name;
}
$this->img_url = json_encode($files_urls);
return parent::beforeSave($insert); // TODO: Change the autogenerated stub
}
Form:
<?php $form = ActiveForm::begin([
'enableAjaxValidation' => true,
'options' => [
'enctype' => 'multipart/form-data'
]
]) ?>
<?= $form->field($model, 'imageFiles[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?>
<div class="form-group">
<?= Html::submitButton('Siguiente', ['class' => 'btn btn-standard']) ?>
</div>
<?php ActiveForm::end() ?>

Yii2 Automatically Login after Registration

I'm creating a website using yii2 framework. I have a problem in registration. I have a modal in home and it contains the sign up form. Now when i trying to register, Yes it saved successful but it only stay in the modal. Now i want is after registering it will automatically login.
This is my sign up form_:
<div class="row">
<div class="col-lg-12">
<?php yii\widgets\Pjax::begin(['id' => 'sign-up']) ?>
<?php $form = ActiveForm::begin(['id' => 'form-signup', 'options' => ['data-pjax' => true]]); ?>
<div class="row">
<div class="col-sm-6">
<?= $form->field($model, 'role')->dropDownList(['2' => 'User', '1' => 'Encoder', '3' => 'Admin']) ?>
<?= $form->field($model, 'username')->textInput(['placeholder' => 'Username....']) ?>
<?= $form->field($model, 'email')->textInput(['placeholder' => 'Email....']) ?>
<?= $form->field($model, 'password')->passwordInput(['placeholder' => 'Password.....']) ?>
</div>
<div class="col-sm-6">
<?= $form->field($model, 'confirmPassword')->passwordInput(['placeholder' => 'Confirm Password.....']) ?>
<?= $form->field($model, 'first_name')->textInput(['placeholder' => 'First Name....']) ?>
<?= $form->field($model, 'middle_name')->textInput(['placeholder' => 'Middle Name....']) ?>
<?= $form->field($model, 'last_name')->textInput(['placeholder' => 'Last Name....']) ?>
</div>
</div>
<center>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className()) ?>
</center>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button', 'style' => 'width: 100%; padding: 10px;']) ?>
</div>
<?php ActiveForm::end(); ?>
<?php yii\widgets\Pjax::end() ?>
</div>
</div>
This is my model:
class SignupForm extends Model
{
public $role;
public $username;
public $email;
public $password;
public $first_name;
public $middle_name;
public $last_name;
public $confirmPassword;
public $verifyCode;
public function rules()
{
return [
['role', 'required'],
['username', 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 20],
['email', 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 30],
['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
['password', 'required'],
['password', 'string', 'min' => 6],
['first_name', 'trim'],
['first_name', 'required'],
['middle_name', 'trim'],
['middle_name', 'required'],
['last_name', 'trim'],
['last_name', 'required'],
['verifyCode', 'captcha'],
['verifyCode', 'required'],
[['confirmPassword'], 'compare', 'compareAttribute' => 'password', 'message' => 'Passwords do not match.'],
];
}
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if (!$this->validate()) {
return null;
}
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->role = $this->role;
$user->first_name = $this->first_name;
$user->middle_name = $this->middle_name;
$user->last_name = $this->last_name;
return $user->save() ? $user : null;
}
}
This is my controller:
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->renderAjax('signup', [
'model' => $model,
]);
}
I don't have any ideas, I think my codes is correct but i don't know why is not working.
UPDATED
When i clicked the button signup it stay only in the modal and when i clicked it again the button the validations is working. It means it saves to database but not automatically login.
you should get the user identity for login
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
$identity = User::findOne(['username' => $model->$username]);
if (Yii::$app->user->login($identity)) {
return $this->goHome();
}
}
}
return $this->renderAjax('signup', [
'model' => $model,
]);
}
see this for more http://www.yiiframework.com/doc-2.0/guide-security-authentication.html
http://www.yiiframework.com/doc-2.0/yii-web-user.html
I have used below code and its working for me . Its also a standard code for YII2 .Controller Action Code :
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
$model= \common\models\User::findOne([$user->id]); //you need to get complete model again and pass it to login function
if (Yii::$app->user->login($model) {
return $this->goHome();
}
}
}
return $this->renderAjax('signup', [
'model' => $model,
]);
}
After couple minutes of step by step debug - it works well
//Signup
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post()) && $model->signup()) { /*Save
to DB first*/
$genmail = $model->email; //get model email value
$identity = User::findOne(['email' => $genmail]); //find user by email
if (Yii::$app->user->login($identity)) { // login user
return $this->redirect('account'); // show accaount page
}
}
return $this->render('signup', [
'model' => $model,
]);
}