ajax validation unique on update - php

I have ajax validation on unique on create it work fine but when I want to update i cant becouse this show message that this name is already used but i not owerwrite this name it is name from database on update click. Its does not matter whcich record i want to update it always show me message that name is already used. Whan can i do to disable message when i not change my input to name which is in base. Now it is so update action automatically filed my inputs but when i not change anythink i have this error on save
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data'], 'id'=>$model->formName(), 'enableAjaxValidation'=>true, 'validationUrl'=>Url::toRoute('category/validation')]) ?>
My controller:
public function actionValidation(){
$model= new SmCategory;
if(Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
{
Yii::$app->response->format='json';
return ActiveForm::validate($model);
}
}
my rules:
public function rules()
{
return [
[['Name'], 'required'],
['Name', 'unique', 'targetClass' => 'common\models\Smcategory', 'message' => 'This name has already been taken.'],
[['Rel_Category', 'IsDeleted'], 'integer'],
[['File'],'file'],
[['Name', 'Label'], 'string', 'max' => 45],
[['Picture'], 'string', 'max' => 255]
];
}

The problem is here :
$model= new SmCategory;
This code is ok for create, not for update since it will not use the existing model for validation, it could be (just an example and assuming id is the primary key) :
public function actionValidation($id = null)
{
$model = $id===null ? new SmCategory : SmCategory::findOne($id);
if(Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
{
Yii::$app->response->format='json';
return ActiveForm::validate($model);
}
}
And you could update validationUrl in your view :
$validationUrl = ['category/validation'];
if (!$model->isNewRecord)
$validationUrl['id'] = $model->id;
$form = ActiveForm::begin([
'options' => ['enctype' => 'multipart/form-data'],
'id' => $model->formName(),
'enableAjaxValidation' => true,
'validationUrl' => $validationUrl,
]);

Related

Ajax validation required when updating user-information yii2

So i reached the Ajax validation part. First i want to say that i read the answers of similar question but it did not helped me.
On registration form validation works good(when i try to register user with existing name it shows me error message), but when i am in the users profile and try to update his name with existing one nothing happens(no error shown).
My model UpdateForm.php rules:
public function rules()
{
return [
[['email', 'password', 'username'], 'required'],
[['email', 'password', 'username'], 'string', 'max' => 50],
[['image'], 'string', 'max' => 255],
['email', 'email'],
[[ 'email', 'username'], 'unique'],
];
}
My UserController action:
public function actionUpdate()
{
$id = \Yii::$app->user->identity->id;
$model = $this->findModel($id);
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
Will appreciate every advice!
configure yii_logger db in your machine (you can find it Yii2 docs).
then run
SELECT FROM_UNIXTIME(log_time, '%Y-%m-%d') log_date, y.* FROM yii_logger y where level = 1 order by log_time desc limit 20;
you may see error backtrace if your code is breaking somewhere.

Yii2 Cannot insert attribute(FK) with id(PK)

i have id there is PK(Auto Inc) from models/order relation with FK id_order from models/preorder, In my CRUD action for example actionCreate, i can't insert attibutes preorder to table because id(PK) from order always null. how do i fix this ?.
here's my controller
$cartPositions = Yii::$app->cart->getPositions();
if (!$cartPositions or $cartPositions === null) {
return $this->redirect(['index']);
}
$dataProvider = new ArrayDataProvider([
'allModels' => $cartPositions,
]);
$model = new Order();
$model_po = new Preorder();
$postData = Yii::$app->request->post();
if ($model->load($postData) && $model_po->load($postData)) {
//model->save(false);
$model->status = 5;
$model_po->id_order = $model->id;
$model->total_cost = Yii::$app->cart->getCost();
$model->date = date('Y-m-d H:i');
$model->data = Yii::$app->cart->getSerialized();
$model_po->name = $model->name;
$model_po->phone = $model->phone;
$model_po->remarks = $model->message;
$model_po->created_at = $model->date;
//$model_po->save();
if (Model::validateMultiple([$model, $model_po]) && $model->save(false) && $model_po->save()) {
Yii::$app->session->setFlash('success', 'Thank You');
Yii::$app->mailer->compose('order/html', [
'model' => $model,
//'model_po' => $model_po,
'dataProvider' => $dataProvider,
])
//->setFrom(Yii::$app->params['email']['from'])
// ->setTo(Yii::$app->params['email']['to'])
// ->setSubject('The site posted a new order')
// ->send();
->setFrom(Yii::$app->params['email']['from'])
->setTo(Yii::$app->params['email']['to'])
->setSubject('The site posted a new Preorder')
->send();
Yii::$app->cart->removeAll();
return $this->render('orderSuccess', [
'model' => $model,
//'model_po' => $model_po,
]);
}
} else
{return $this->render('create_po', [
'model' => $model,
'model_po' => $model_po,
'dataProvider' => $dataProvider,
]);}
}
models/order
public function rules()
{
return [
[['status', 'total_cost', 'date', 'data', 'name', 'phone'], 'required'],
[['code_order'], 'autonumber', 'format'=>'orderNum', 'digit'=>4],
[['status', 'total_cost'], 'integer'],
[['date'], 'safe'],
[['data', 'message'], 'string'],
[['name', 'email', 'phone'], 'string', 'max' => 255]
];
}
model/preorders
public function rules()
{
return [
[['id_order', 'address'], 'required'],
[['id_order'], 'integer'],
[['created_at', 'updated_at'], 'safe'],
[['address', 'remarks'], 'string', 'max' => 500],
[['id_order'], 'exist', 'skipOnError' => true, 'targetClass' => Order::className(), 'targetAttribute' => ['id_order' => 'id']],
];
}
error info :
Integrity constraint violation – yii\db\IntegrityException
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'id_order' cannot be null
The SQL being executed was: INSERT INTO preorder (address, id_order, name, phone, remarks, created_at) VALUES ('', NULL, 'Name', '121324325', '', '2016-07-23 17:01')
Error Info: Array
(
[0] => 23000
[1] => 1048
[2] => Column 'id_order' cannot be null
i was try getPrimaryKey() and last insert id() not work and i was try to remove $modelpo->id_order = $model->id the result is two tables filled but id_order is 0
$model->id is null until successful $model->save() so you should not assign its value to $model_po->id_order before that.
This is a good place for transaction so you can validate data first, then make sure Order is saved and then save Preorder with proper id_order.
Take a look at link() method as well.
why don't you use afterSave()? it will definetely solve your problem

data update issues in gridview in yii2

I have a table "attendance" and when I perform create action on it ,it works properly like the screen-shot below,
In this form I have used jquery to disable form field 'time in' and 'time out' if the status value is "Absent" or "Leave".
my jquery code is below
<script>
$(document).ready(function() {
$("#status_id").on('change', function()
{
if($("#status_id").val()=='Absent' || $("#status_id").val()=='Leave')
{
$("#attendance-time_in").val('');
$('#attendance-time_in').attr('disabled', true);
$("#attendance-time_out").val('');
$('#attendance-time_out').attr('disabled', true);
}
else {
$("#attendance-time_in").val();
$('#attendance-time_in').attr('disabled', false);
$("#attendance-time_out").val();
$('#attendance-time_out').attr('disabled', false);
}
});
});
</script>
and _form.php code is
<?= $form->field($model, 'status', ['inputOptions' => ['class' => 'form-control','id' => 'status_id']])
->dropDownList([ 'Present' => 'Present', 'Absent' => 'Absent', 'Leave' => 'Leave',], ['prompt' => 'Select status']); ?>
<?=
$form->field($model, 'time_in')->widget(TimePicker::classname(), [
'name' => 'time_in',
'options'=>[
'id'=>'attendance-time_in',
],
]);
?>
<?=
$form->field($model, 'time_out')->widget(TimePicker::classname(), [
'name' => 'time_out',
'options'=>[
'id'=>'attendance-time_out',
],
]);
?>
its works fine for create action but when i update any data
like if i update data of arsalan khalid ,and i put absent instead of present the jquery works properly but when i click on update button it does not update the 'time in' and 'time out' attributes while all other attributes gets updated.for 'time in' and 'time out' it takes the previous value that it have i.e 9:40am and 5:52pm but i want it should have null values as i have selected "Absent" in status.
AttendanceController Update Action
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
Attendance models Rules
public function rules()
{
return [
[[ 'staff_id'], 'integer'],
[['daytime'], 'safe'],
[['staff_id'], 'required'],
[['status','time_in', 'time_out'], 'string', 'max' => 45]
];
}
i am new in yii2.
Many thanks in advance.
What you need to do is create another rule inside your Attendance model.
[['time_in', 'time_out'], 'filter', 'filter' => function ($value) {
if($this->status_id == AbsentStatus->status_id)
{
return null;
}
return $value;
}],
This way, if the status_id is equal to the AbsentStatus, you set the value of time_in and time_out as null.
Edit: you should substitute 'AbsentStatus->status_id' in the condition to the value of the id of your absent status.
I think one problem is the html id name fo the fields
In Yii2 the html id of an input field inside an active form is, by default, formed automatically in the format 'classname-fieldname' (all lowercase).
eg: namimg the model class = "Customer" the filed name is like
<input type="text" id="customer-name" class="form-control" name="Customer[name]" maxlength="16">
Then your field id should named 'attendance-status_id' , 'attendance-timein_id', and so on...
Try using this format for the html id
And second, just for test, modify your controller this way
if ($model->load(Yii::$app->request->post()) && $model->save(false)) {
adding false to save() in saving process are not involved the validation rules.

Yii2: compare validation of password and repassword

I'm a beginner of Yii, that's why can't figure out, what's wrong.
I use the same model - Users - for login, registration and edition profile.
Users model:
class Users extends \yii\db\ActiveRecord {
public $password_repeat; //have no this value in DB, that's why write it as property directly. Need only for profile editing
public function rules() {
return [
[['username', 'password', 'authKey', 'accessToken'], 'safe'],
[['username', 'password'], 'required'],
[['username', 'password', 'authKey', 'accessToken'], 'string', 'max' => 255],
[['is_admin'], 'boolean'],
//don't use scenarios() here. Use 'on' instead
['password_repeat', 'required', 'on' => 'update'],
['password_repeat', 'compare', 'compareAttribute'=>'password', 'message'=>"Passwords don't match", 'on' => 'update' ],
];
}
}
view snippet:
<?php $form = ActiveForm::begin([
'id' => 'data-form',
'options' => ['class' => 'form-horizontal', 'enctype' => 'multipart/form-data'],
'fieldConfig' => [
'template' => "{label}\n<div class=\"col-lg-3\">{input}</div>\n<div class=\"col-lg-6\">{error}</div>",
'labelOptions' => ['class' => 'col-lg-1 control-label'],
],
]); ?>
<?= $form->field($user_data, 'username') ?>
<?= $form->field($logo_data, 'imageFile')->fileInput() ?>
<?= $form->field($user_data, 'password')->passwordInput(['value'=>''])?>
<?= $form->field($user_data, 'password_repeat')->passwordInput(['value'=>''])?>
<?= Html::submitButton('Zapisz', ['class' => 'btn btn-primary btn-block', 'name' => 'data-button']) ?>
<?php ActiveForm::end(); ?>
Site controller action:
public function actionProfile(){
//3 model instances to retrieve data from users && company_profiles and logo
$user_data = Users::find()->where(['id'=>Yii::$app->user->id])->one();
$company_profile_data = CompanyProfiles::find()->where(['user_id'=>Yii::$app->user->id])->one();
$logo_data = new UploadLogo();
//here I upload file through $logo_data
if (isset($_POST['Users'])){
$user_data->username = $_POST['Users']['username'];
$company_profile_data->firm_data = $_POST['CompanyProfiles']['firm_data'];
//other assignments
$user_data->scenario = 'update'; //specially for 'profile' page
if (($_POST[Users][password] !== '') && ($_POST[Users][password_repeat]) !== '' && ($_POST[Users][password] == $_POST[Users][password_repeat]))
$user_data->password_repeat = $user_data->password = md5($_POST[Users][password]); //MAYBE, problem is here?
$user_data->update();
$company_profile_data->update();
}
return $this->render('profile', ['user_data' => $user_data, 'company_profile_data' => $company_profile_data, 'logo_data' => $logo_data]);
}
I use update scenario for profile editing page. During this scenario password_repeat is required and need to be the same as password. But it doesn't work as expected.
A: When i try to submit form without entered password AND repass, I see message "can't be blank" only for password. Then I put value in ONLY pass input, and page reloads (DB table doesn't changes), and after reloading I see message "can't be blank" this time for repass field! But the most strange is that before next page reloading everything work normal. After reloading goto A; :)
If I delete scenario, everything is ok with validation. But I can't delete it, cause in this case registration fails (repass field becomes required to fill).
So, what need I to do my with pass-repass functionality to work it fine (with scenario 'update')? Where is mistake?
Got it! I just need to move this codeline:
$user_data->scenario = 'update';
from IF stmt. And now I want to make a habit to assign scenario property directly under creating model instance.

Yii2 ajax validation not work

I was trying to validate my YII2 register form but it not work. In view:
$form = ActiveForm::begin([
'id' => 'register',
'options' => ['accept-charset'=>'utf-8'],
'validateOnChange' => false,
'enableAjaxValidation' => true,
'validateOnSubmit' => true,
])
In controller:
$model = new MUser();
if($model->load(Yii::$app->request->post()) && Yii::$app->request->isAjax)
{
$model->refresh();
Yii::$app->response->format = 'json';
return ActiveForm::validate($model);
}
elseif($model->load(Yii::$app->request->post()) && $model->save())
{
\\do something
}
In Model:
public function rules()
{
return [
[
'username',
'unique',
'targetClass' => 'com\modules\admin\models\MUser',
'message' => 'Username exist',
]
];
}
Can anyone let me know what wrong I am doing?
change
return ActiveForm::validate($model)
TO
echo json_encode(ActiveForm::validate($model));
\Yii::$app->end();
ActiveForm::validate($model) is an array it needs to be represented in json form which is done by json_encode and \Yii::$app->end(); is making sure that the application stop on just checking.Also make sure you have after the namespace :
use yii\web\Response;
use yii\widgets\ActiveForm;
But By doing so the submission via ajax of your form will not work the perfect way is using validationUrl.

Categories