Yii2 Ajax Validation not validating one field unique - php

Very weird behavior i found out with yii2 ajax validation i found today.
Basically i was trying to perform ajax validation on 1 field of the form to check that the input is unique and not found anywhere in that field of that table.
If you ask me the following code should work correctly:
In model:
public function scenarios(){
return ['update' => ['username']];
}
public function rules(){
return [['username'], 'unique'];
}
In Controller:
public function actionUpdate(){
$user = User::findmodel.. bla bla
some more bla bla..
if(Yii::$app->request->isAjax){
$user->setScenario('update');
$user_post_ajax = Yii::$app->request->post('User');
$user->username = $user_post_ajax['username'];
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($user);
}
some more bla bla bla..
}
In View:
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($user, 'username', ['enableAjaxValidation' => true])->textInput() ?>
<?= Html::submitButton('Save', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
This should work, but it doesn't, it doesn't display the validation errors, in this case something like: 'Username is already taken', it doesn't display neither valid nor invalid. It performs the ajax request, and i can see the json response in the dev tools but it doesn't display at all. But, When you move the $user->setScenario('update'); outside the if condition, above the if(Yii::$app->request->isAjax) only then it works perfectly fine. I don't understand this, am i missing something? Why using setScenario when ajax request changes the behavior?

You're overriding the scenarios() function from the Yii Model, thus not validating any attributes.
Check: https://github.com/yiisoft/yii2/blob/master/framework/base/Model.php#L184
What you should do, is:
public function rules(){
return [['username'], 'unique', 'on'=>['update']];
}

Related

Cannot load form yii2

I am newbie to yii2. I am trying to create my simple form in yii2 to retrieve password. Here is class code:
<?php
namespace app\models;
use yii\base\Model;
class RetrievePasswordForm extends Model
{
public $email;
public function rules()
{
return [
['email', 'required'],
['email', 'email'],
];
}
}
Here is action code:
$model = new RetrievePasswordForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()){
return $this->render('retrievepassword-confirm', ['model' => $model]);
} else {
return $this->render('retrievepassword', ['model' => $model]);
}
My form looks like this:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
$this->title = 'Retrieve password';
$this->params['breadcrumbs'][] = $this->title;
?>
<h1><?= Html::encode($this->title) ?></h1>
<p>We will send link to retrieve your password to the following email:</p>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'email')->textInput(['style'=>'width:200px'])?>
<div class="form-group">
<?= Html::submitButton('Send', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
The problem is that $model->load(Yii::$app->request->post()) always returns false, so when I am clicking "submit" button, page just reloads.
I am currently working without database. I am just creating form and trying to go to another form, when valid data received in model. Thanks for help.
Try explicitally assign the method and the action to the active Form
Then Assuming that your target action is named actionRetrivePassword
<?php $form = ActiveForm::begin([
'method' => 'post',
'action' => Url::to(['/site/retrivepassword']
); ?>
I'll go with I feel it's wrong, if this doesn't help, please give more information.
It's a registration form, so I assume you need email and password for that (since you have those columns in database). But you also declared public member $email in your model. This removes any value associated to $email from database. Therefore, remove this line:
public $email;

get input data in controller yii2?

i am trying get input field from a form in yii2. i need to use it in a controller depending on the value. i am trying to see the value using var_dump but it is not working. i am getting "NULL" as the value.. Or is there a way to make a form use different controllers.
controller
public function actionBlog()
{
$thumbs= new Thumbs;
$thumbs->user=Yii::$app->user->identity->email;
$thumbs->topic_id=Yii::$app->getRequest()->getQueryParam('id');
$ra=Yii::$app->request->post('rate');
var_dump($ra);
if(ra=='down'){
if ($thumbs->load(Yii::$app->request->post()) && $thumbs->validate()) {
$thumbs->load($_POST);
$thumbs->save();
return $this->refresh();
}
} else {
return $this->refresh();
}
return $this->render('blog',[
'thumbs' => $thumbs,
]);
}
this is my view
<?php $form = ActiveForm::begin(['id' => "contact-form"
]);
?>
<?= $form->field($thumbs, 'rate')?>
<?= Html::submitButton('Update', ['blog'], ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
i also tired using doing it like this
$rr=Yii::$app->request->post($thumbs)['rate'];
var_dump( $rr);
and i get this error:
Illegal offset type in isset or empty
You have a error in if(ra=='down') condition, '$' is missing.
If I remember right .. you should try
$ra=Yii::$app->request->post(['Thumbs']['rate']);

Rendering partial form

Is there any way to render partial view which contains a part of form that it's main part is in another view file with AJAX?
I exactly mean one form variable:
`<?php $form = ActiveForm::begin(['enableAjaxValidation' => true,]); ?>`
For Example :
Controller
public function actionOlddetform()
{
return $this->renderAjax('_olddet');
}
View
<?php $form = ActiveForm::begin(['enableAjaxValidation' => true,]); ?>
<?= $form->field($model, 'date')->input() ?>
<?= $form->field($model, 'annotations')->textarea(['rows' => 3]) ?>
<div id="details-form"></div>
<?php ActiveForm::end(); ?>
Part of form included with AJAX for details-form container depends on date value. I know how to check date and show any content of that partial view but when I want to include a part of form I get an error:
PHP Notice 'yii\base\ErrorException' with message 'Undefined variable: form'
It seems you forgot to actually pass the model into your view:
public function actionOlddetform()
{
return $this->renderAjax('_olddet', ['model' => $dataModel]);
}
And if you want to render "sub-views" from your main view, you need to pass the variables in there as well (even though I don't see a render call in your view):
<?= $this->render('_formPart', ['form' => $form, 'model' => $model]) ?>

Relational attribute in Yii2 form

I am trying to get to figure out the proper way of handling a form receiving relational data in Yii2. I haven't been able to find any good examples of this. I have 2 models Sets and SetsIntensity, every Set may have one SetsIntensity associated with it. I'm am trying to make a form where you can input both at the same time. I'm not sure how to handle getting the input for a particular field 'intensity' in SetsIntensity.
Where
$model = new \app\models\Sets();
If I put it in the field like this client validation won't work and the attribute name is ambiguous and saving becomes difficult
<?= $form->field($model, 'lift_id_fk') ?>
<?= $form->field($model, 'reps') ?>
<?= $form->field($model, 'sets') ?>
<?= $form->field($model, 'type') ?>
<?= $form->field($model, 'setsintensity') ?>
I would like to do something like this but I get an error if I do
<?= $form->field($model, 'setsintensity.intensity') ?>
Exception (Unknown Property) 'yii\base\UnknownPropertyException' with message 'Getting unknown property: app\models\Sets::setsintensity.intensity'
I could do make another object in the controller $setsintensity = new Setsintensity(); but I feel this is a cumbersome solution and probably not good practice especially for handling multiple relations
<?= $form->field($setsintensity, 'intensity') ?>
relevant code from SetsModel
class Sets extends \yii\db\ActiveRecord
{
public function scenarios() {
$scenarios = parent::scenarios();
$scenarios['program'] = ['lift_id_fk', 'reps', 'sets', 'type', 'intensity'];
return $scenarios;
}
public function rules()
{
return [
[['lift_id_fk'], 'required'],
[['lift_id_fk', 'reps', 'sets','setsintensity'], 'integer'],
[['type'], 'string', 'max' => 1],
['intensity', 'safe', 'on'=>'program']
];
}
public function getSetsintensity()
{
return $this->hasOne(Setsintensity::className(), ['sets_id_fk' => 'sets_id_pk']);
}
SetsIntensity Model
class Setsintensity extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'setsintensity';
}
public function rules()
{
return [
[['sets_id_fk', 'intensity', 'ref_set'], 'required'],
[['sets_id_fk', 'intensity', 'ref_set'], 'integer']
];
}
public function getSetsIdFk()
{
return $this->hasOne(Sets::className(), ['sets_id_pk' => 'sets_id_fk']);
}
}
I was also thinking maybe I could put in a hasOne() relation for the specific attribute 'intensity' in 'Sets'
You should simply try this :
<?= $form->field($model->setsintensity, 'intensity') ?>
EDIT : And because "every Set may have one SetsIntensity", you should check this relation before displaying form, e.g. :
if ($model->setsintensity===null)
{
$setsintensity = new SetsIntensity;
$model->link('setsintensity', setsintensity);
}
PS: link method requires that the primary key value is not null.

Yii2 save model to database

I'm trying to do simple CRUD application with Yii2, but when I'm trying to save data, no validation errors appears and $model->validate() returns false. Here's my code:
public function actionCreate()
{
$model = new Game();
if($model->load(Yii::$app->request->post()) && $model->save())
{
$this->redirect(['game-list']);
}
return $this->render('create', ['model' => $model]);
}
So, $model->load() returns true and here is my rules() in my model:
public function rules()
{
return [
[['title', 'subtitle', 'description'], 'required'],
[['id_type', 'is_active', 'picture'], 'default'],
];
}
I have seven columns in DB (this 6 + id as a primary key). I will be glad if anyone help me.
UPD:
View:
<? $form = ActiveForm::begin(array('options' => array('class' => 'form-horizontal'))); ?>
<?= $form->errorSummary($model); ?>
<?= $form->field($model, 'title')->textInput(); ?>
<?= $form->field($model, 'subtitle')->textInput(); ?>
<?= $form->field($model, 'description')->textInput(); ?>
<div class="form-actions">
<?= Html::submitButton(Yii::t('app', $model->isNewRecord ? 'Create' : 'Update')); ?>
</div>
<? ActiveForm::end(); ?>
My mistake was obviously stupid, but here it is. I've created method beforeSave in my model and haven't filled it and totally forgot about it's existence. So, 'cause it's not returned true - validate() cannot pass properly. Sorry for wasted time.

Categories