Textfield Mandatory On basis of radio button selection- Yii2 - php

I'm having radio button with two value i.e, Individual and Firm.
I am looking for one scenario where if radio button having value Firm is selected, then CompanyName textinput should act as mandatory (required) field. And, when radio button having value Individual is selected, Then CompanyName textinput should act as Optional field.
I was not getting how to do it. I tried to add addAttribute in CompanyName textinput as mandatory. but it didn't worked as RegisterForm.php (model) is having few rules specified.
So, any idea how to do it. I'm not getting. Any help ?
register.php (view)
<?php $form = ActiveForm::begin(['id' => 'register-form']); ?>
.
.
.
<?= $form->field($model, 'AdminType')
->radioList(array('Individual'=>'An Individual', 'Firm'=>'Firm/Company/Group of Employees'))
->label('Are You')?>
<?= $form->field($model, 'CompanyName')->textInput()->label('Company Name') ?>
<div class="form-group">
<?= Html::submitButton('Register', ['class' => 'btn btn-success', 'name' => 'register-button' ]) ?>
</div>
<?php ActiveForm::end(); ?>
<script>
$('input[type="radio"]').click(function()
{
if($(this).attr("value")=="Firm")
{
$('#registerform-companyname').addAttribute("required");
}
});
</script>
RegisterForm.php (model)
<?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'],
];
}

First of all, having any kind of front end validation is BAD, as i can circumvent it by generating a post programmatically, and it will save the record without any problems, making a possibility of inconsistent records a reality.
What you want to do instead is create a custom validation rule function in your model, as well as add the rule to the validation array:
<?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, $params)
{
if($this->$attribute === 'Firm' && empty($this->$attribute))
$this->addError('CompanyName', 'CompanyName cannot be blank');
}
}
?>
Now your field generating code should look like this
<?= $form->field($model, 'CompanyName')->textInput()->label('Company Name')->error() ?>
Hope this helps you
Edit: As I am used to working with AR classes(which generally, when generated with gii, have validation automatically ), it did not cross my mind that you are using just a form model ( the one that was given as an example in the basic app)
forget the ->error() in the field, also make sure you have the row
if ($model->load(Yii::$app->request->post()) && $model->validate()) {...}
in your action

At last I Got,
['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';
}"],

Related

yii2 - SQLSTATE[23000]: Integrity constraint violation: 1048

I'm new to yii2, I'm trying to send a request to the database, but it comes out that such columns cannot be null, although when checking through #var_dump I can see the sending data, what is the matter and how to fix it
---> Controller
public function actionSignup()
{
$model = new Signup();
if (isset($_POST['Signup'])) {
$model->attributes = Yii::$app->request->post('Signup');
if ($model->validate()) {
$model->signup();
# code...
}
}
return $this->render('signup', ['model'=>$model]);
---> View page
<?php
use \yii\widgets\ActiveForm;
?>
<?php
$form = ActiveForm::begin(['class'=>'form-horizontal']);
?>
<?= $form->field($model,'email')->textInput(['autofocus'=>true]) ?>
<?= $form->field($model,'password')->passwordInput() ?>
<div>
<button type="submit" class="btn primary-btn">Submit</button>
</div>
<?php
ActiveForm::end();
?>
---> Model
class Signup extends Model
{
public $email;
public $password;
public function reles()
{
return [
[['email', 'password'], 'required'],
['email', 'email'],
['email', 'unique', 'targetClass'=>'app\models\User'],
['password', 'string', 'min'=>2,'max'=>10]
];
}
public function signup()
{
$user = new User();
$user->email = $this->email;
$user->password = $this->password;
return $user->save();
}
---> phpmyadmin database
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord
{
}
--> var_dump
--> sql
Try this:
**
* Signs user up.
*
* #return mixed
*/
public function actionSignup()
{
$model = new SignupForm()
//Sign up if it is post request
if ($model->load(Yii::$app->request->post()) && $model->signup()) { //Here YOU LOAD your POST data in to the Lodal using load() method.
Yii::$app->session->setFlash('success', 'Thank you for registration. Please check your email for further instructions.', false);
return $this->goHome();
} else {
Yii::$app->session->setFlash('success', 'Sorry, you can not register right now.', false);
return $this->redirect('/login');
}
}
In Model
First of all, the method for attribute rules is called "rules" I don't know if it's a typo from you in the question or this is the problem; If there are no rules for user input data the returned values will be NULL, I have faced this issue before, I didn't include a rules() method (or in your case it's name is not correct) and the model returned null for attribute values. Your code have to be:
public function rules()
{
return [
[['email', 'password'], 'required'],
['email', 'email'],
['email', 'unique', 'targetClass'=>'app\models\User'],
['password', 'string', 'min'=>2,'max'=>10]
];
}
Technical note: normally, or based upon my understanding a password should have a minimum of 8 not 2 characters, if the password entered is only 2 characters it can be brute-forced in a second.
In Controller
As in #Serghei Leonenco's Answer, Yii2 already provides some functions to use to handle post requests and so, so please stick to Yii2 functions it can enhance your app security
So in the actionSignup() method the code ought to be
public function actionSignup()
{
$model = new Signup();
// Loads the post request directly onto the model and validates it against the model rules() method
if($model->load(Yii::$app->request->post()) && $model->validate){
$model->signup();
// Model validated and saved successfully, IT OUGHT TO BE SAVED IN THE DATABASE AT THIS POINT
// Here you can set a flash or redirect the user to another page
}
return $this->render('signup', ['model'=>$model]);
}
In View
At last, in your view code it's better to use Yii2 internal functions for Html buttons
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary']) ?>
Of course don't forget to use yii\helpers\Html
use yii\helpers\Html;

Validation for form

Please help with setting rules (). The thing is, I have a form. Where 2 fields are present. If all fields are empty, the form cannot be submitted, but if at least ONE is not empty, then the form can be submitted. Can you help me please, I'm new at it?
Here's my form
<?php $form = ActiveForm::begin() ?>
$form->field($model, 'field1')->textInput();
$form->field($model, 'field2')->textInput();
<?php $form = ActiveForm::end() ?>
And this's my model, but this rule does not quite suit me. Because the rules require you to fill in all the fields. And the main thing for me is that at least one, but was filled, so i could send the form. If ALL fields are empty, then validation fails.
public function rules()
{
return [
[['field1', 'field1'], 'require'] ]}
Should I add something in controller maybe?
You have TYPO in rules: use required
public function rules()
{
return [
[['field1', 'field1'], 'required']
];
}
You can use yii\validators\Validator::when property to decide whether the rule should or shouldn't be applied.
public function rules()
{
return [
[['field1'], 'required', 'when' => function ($model) {
return empty($model->field2);
}]
[['field2'], 'required', 'when' => function ($model) {
return empty($model->field1);
}]
];
}
The when property is expecting a callable that returns true if the rule should be applied. If you are using a client side validation you might also need to set up the yii\validators\Validator::whenClient property.
You can use standalone validation:
public function rules()
{
return [
[['field1', 'field2'], MyValidator::className()],
];
}
And create a new class like follows:
namespace app\components;
use yii\validators\Validator;
class MyValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
if (empty($model->filed1) and empty($model->field2)) {
$this->addError($model, $attribute, 'some message');
}
}
}

Exception (Unknown Property) 'yii\base\UnknownPropertyException' with message 'Getting unknown property: app\models\User::repeat_password'

I am new in Yii framework. This is my first post in stackoverflow for related framework. My problem is how to show non model input field in the view page. Please check my controler and view code.
controllers
public function actionRegister() {
$model = new User();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
//Insert data code here...
return $this->render('entry-confirm', ['model' => $model]);
} else {
return $this->render('entry', ['model' => $model]);
}
}
views(entry.php)
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'username') ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'repeat_password')->passwordInput() ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
models(User.php)
namespace app\models;
use Yii;
class User extends \yii\db\ActiveRecord {
public static function tableName() {
return 'user';
}
public function rules() {
return [
[['username', 'password', 'email'], 'required'],
[['username', 'password', 'email'], 'string', 'max' => 128],
['email', 'email', 'message' => "The email isn't correct"],
['email', 'unique', 'message' => 'Email already exists!'],
['repeat_password', 'required'],
[['repeat_password'], 'string', 'min'=>6, 'max'=>40],
['password', 'compare', 'compareAttribute'=>'repeat_password'],
];
}
public function attributeLabels() {
return [
'id' => 'ID',
'username' => 'Username',
'password' => 'Password',
'email' => 'Email',
];
}
}
Output
I have 3 column in my user table. Columns are username, email and password but repeat_password is not in my table column. This is a non model input field. So I am getting above error message. Please help me and let me know how to fix it.
You have to add new public property to User.php (model class file) as
class User extends ActiveRecord
{
public $repeat_password;
Please refer to this first
http://www.yiiframework.com/doc-2.0/guide-structure-models.html
http://www.yiiframework.com/doc-2.0/guide-start-forms.html
It will not take much time.
Don't forget to add its validation rules in rules method of User.php
http://www.yiiframework.com/doc-2.0/guide-structure-models.html#safe-attributes
The problem is related to the fact you are using a
<?= $form->field($model, 'repeat_password') ?>
that not exist for the User Model ..
you should create a a FormModel (eg: UserInput with also this repeat_password field ) for manage the correct input and then in action mange properly the assigment from your formModel/UserInput model and User model for store
for build a proper form model class you can take a looka at this guide http://www.yiiframework.com/doc-2.0/guide-start-forms.html

Yii2: how to enable form validation when using multiple models in a view?

What I meet is almost like this:
I have a create form, and the form contains two model's attribute;
I pass them from controller to view, and add rules to validate attribute in both model;
But the form validation did not work well - a model's validation is
not work.
I have no idea about how to resolve this, thanks for help!
And I find a reference article - Complex Forms with Multiple Models, but it is TBD.
Here is my sample code.
Controller - SiteController.php:
namespace task\controllers;
use yii\web\Controller;
use task\models\Task;
use task\models\Customer;
class Task extends Controller
{
public function actionCreate()
{
$model = new Task;
$customerModel = new Customer;
// load, validate, save ...
return $this->render('create', [
'model' => $model,
'customerModel' => $customerModel
]);
}
}
Model - Task.php, Customer.php:
namespace task\models;
use yii\db\ActiveRecord;
class Task extends AcitveRecord
{
public $title, $published_at;
public function rules()
{
return [
[['title', 'published_at'], 'required'],
['published_at', 'match', 'pattern' => '/patten for time/']
];
}
}
namespace task\models;
use yii\db\ActiveRecord;
class Customer extends ActiveRecord
{
public $name;
public function rules()
{
return [
['name', 'required'],
];
}
}
View - create.php:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'title')->textInput() ?>
<?= $form->field($model, 'publish_at')->textInput() ?>
<?= $form->field($customerModel, 'name')->textInput() ?>
<?= Html::submitButton('submit')?>
<?php ActiveForm::end(); ?>
This can be an option. You can try it by creating an custom model, like ContactForm something like this:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
/**
* CustomModel is the model behind the contact form.
*/
class CustomModel extends Model
{
public $attributeFromModel1;
public $attributeFromModel2;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
// attributeFromModel1, attributeFromModel2 are required
[['attributeFromModel1', 'attributeFromModel2'], 'required'],
// ['email', 'email'],
['attributeFromModel1','YourRule']
// verifyCode needs to be entered correctly
['verifyCode', 'captcha'],
];
}
/**
* #return array customized attribute labels
*/
public function attributeLabels()
{
return [
'atttributeFromModel1' => 'Your Label',
'atttributeFromModel2' => 'Your Label ',
];
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
$customerModel = Customer::findOne($id);
if (!isset($model, $customerModel)) {
throw new NotFoundHttpException("The user was not found.");
}
$model->scenario = 'update';
$customerModel->scenario = 'update';
if ($model->load(Yii::$app->request->post()) && $customerModel->load(Yii::$app->request->post())) {
$isValid = $model->validate();
$isValid = $customerModel->validate() && $isValid;
if ($isValid) {
$model->save(false);
$customerModel->save(false);
return $this->redirect(['view', 'id' => $id]);
}
}
return $this->render('update', [
'model' => $model,
'customerModel' => $customerModel,
]);
}

How to create Yii form field which shouln't appear in Database

I'm using Yii MongoDbSuite.
I need to create form field for password repeat validation, which shouldn't appear in MongoDB.
Because of I'm using yii forms, all fields which i want to add in view i should declare as public in my model. But my model extend MongoDocument, so all decleared public fields after save() appear in MongoDb. How can i declare field, wich would appear in model, but doesn't appear in Mongo.
In a CActiveRecord model, you can add a property that is not a database column. And it will be treated almost the same as other database backed properties.
public $new_password;
public $new_password_confirm;
...
return array(
array('E_NAME, E_EMAIL, new_password, new_password_confirm', 'required'),
array('new_password', 'compare', 'compareAttribute'=>'new_password_confirm'),
...
<div class="row">
<?php echo $form->labelEx($model, 'new_password'); ?>
<?php echo $form->passwordField($model, 'new_password'); ?>
<?php echo $form->error($model,'new_password'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model, 'new_password_confirm'); ?>
<?php echo $form->passwordField($model, 'new_password_confirm'); ?>
<?php echo $form->error($model,'new_password_confirm'); ?>
</div>
Also a CFormModel model is a model that has no database backed properties.
Unfortunately, due to the way YiiMongoDBSuite works, Nikos' answer won't work completely.
YiiMongoDBSuite saves in a weird way to accomodate the schemaless design of MongoDB by reflecting all public attributes into database attributes.
It starts (in the update function) calling toArray: https://github.com/canni/YiiMongoDbSuite/blob/master/EMongoDocument.php#L593 and then finishs in _toArrray with setting all public attributes as databse properties: https://github.com/canni/YiiMongoDbSuite/blob/master/EMongoEmbeddedDocument.php#L304.
What you can do is set some protected attributes in your model. This should make them not go to the database and be saved, i.e.
class MyAwesomeModel{
public $somedbvar;
protected $somenotdbvar;
}
You can then use that protected property the same way that Nikos' shows.
To improve on #Sammaye 's answer, it is correct, YMDS does assign attributes from class variables.
Although this is not the problem here. The problem here imo, is lazy coding.
Example on how I would tackle the problem
User Model (based on the suit's example)
class User extends EMongoDocument
{
public $username;
public $email;
public $password;
public function getCollectionName()
{
return 'users';
}
public function rules() {
return array(
array('username, email, password', 'required'),
);
}
public function attributeLabels()
{
return array(
'username' => 'UserName',
'email' => 'Email',
'password' => 'Password',
);
}
public static function model($className = __CLASS__)
{
return parent::model($className);
}
public function getForm()
{
$form = new UserForm();
$form->userid = $this->primaryKey();
return $form;
}
}
Form Model :
<?php
class UserForm extends CFormModel
{
public $userid; //something to refer back to your User model on save, you might need this as a hidden field
public $username;
public $email;
public $password;
public $password_again;
public function rules()
{
return array(
array('username, email, password, password_again', 'required'),
array('password', 'compare', 'compareAttribute'=>'password_again', 'strict'=>true),
);
}
public function attributeLabels()
{
return array(
'password_again'=>'Re-type Password',
);
}
public function save()
{
if($this->validate())
{
$user = User::findByPk($this->userid);
$user->username = $this->username;
$user->email = $this->email;
$user->password = hash('sha512',$this->password);
if($user->save())
{
//do stuff
}
}
}
}
And in the view:
<?php
$model = $model->form;
$form = $this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation'=>true,
'enableClientValidation'=>true,
'focus'=>array($model,'firstName'),
));
Ofcourse this is just an example on how to solve your problem without running into problem after problem
(a lazy way that would work btw, is simply declaring an attribute unsafe and never it would never be saved)

Categories