Yii2 client side validation refreshes the page on form submit - yii2

I am trying to perform client side check but the page is being refreshed. My rules looks like:
public function rules()
{
return [
[['email'], 'required'],
[['email','cron'], 'string'],
[['email'], 'string', 'max' => 100],
[['cron', 'group', 'type'], 'integer'],
[['email'], 'unique'],
['group', 'required', 'when' => function($model){
return $model->type == 1;
}, 'whenClient' => 'function(attribute, value){
return 1==2;
}']
];
}
The form enableClientValidation is switched to true like this :
<?php $form = ActiveForm::begin([
'enableClientValidation' => true
]) ?>
Where is my mistake ? Thank you in advance!

You need to set enableAjaxValidation property of AcitveForm:
$form = ActiveForm::begin([
'id' => 'form-id',
'enableAjaxValidation' => true,
]);
Controller
if ($model->load(Yii::$app->request->post())) {
if(Yii::$app->request->isAjax) {
return $this->asJson(ActiveForm::validate($model));
}
}
Yii2 Ajax Validation
asJson()

<?php $form = ActiveForm::begin([
'id' => 'form',
'enableAjaxValidation' => true
]) ?>

Related

Yii2 - Dropdownlist to load other attributes

I have this Model Class
public function attributeLabels()
{
return [
'id' => Yii::t('course', 'ID'),
'course_code' => Yii::t('course', 'Course Code'),
'course_type' => Yii::t('course', 'Course Type'),
'course_title' => Yii::t('course', 'Course Title'),
'course_unit' => Yii::t('course', 'Course Unit'),
];
}
On Dropdownlist change, I want to load and display course_code, course_type, course_title, and course_unit. But should only save course_title. The other should only be displayed and not save, except course_title.
Am ableto display only course_title. This is my view for the dropdown list.
<?= $form->field($modelDetail, "course_id")->widget(Select2::classname(), [
'data' => ArrayHelper::map(app\modules\course\models\CourseMaster::find()->where(['is_status'=>0])->all(),'id','course_title'),
'language' => 'en',
'options' => ['placeholder' => '--- Select Course ---',
],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
This is what I have done.
But I want to achieve this.
How do I display other attributes as textInput() or label without saving in database. Thanks
Controller
public function actionCreate()
{
$modelDetail = new CourseMaster();
if (Yii::$app->request->isAjax && $modelDetail->load(Yii::$app->request->post())) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($modelDetail);
}
if ($modelDetail->load(Yii::$app->request->post())) {
$modelDetail->attributes = $_POST['CourseMaster'];
if($modelDetail->save())
return $this->redirect(['index']);
else
return $this->render('create', ['modelDetail' => $modelDetail,]);
} else {
return $this->render('create', [
'modelDetail' => $modelDetail,
]);
}
}
If you want to only display other fields without sending it on form submit, you can mark field as disabled:
<?= $form->field($modelDetail, 'course_code')->textInput([
'disabled' => true,
]) ?>
This will render input which cannot be edited directly and it will not be sent on form submit.
Well You can concat the data in the label of dropdown itself, will be an easier option. Use closure on the third argument in ArrayHelper::map($array, $from, $to, $group = null) as follows.
ArrayHelper::map(
app\modules\course\models\CourseMaster::find()->where(['is_status'=>0])->all(),
'id',
function($model){
return $model['course_title']." - ".$model['course_code'];
}
)

Set enablePushState = false on specific urls inside Pjax container (Yii2)

I need pjax to work on change status click and it's working fine but don't want it to change the URL as well. Below is the code:
<?php Pjax::begin(['id'=>'pjax-container-agency-index', 'timeout' => 10000, 'enablePushState' => true]); ?>
<?= GridView::widget([...,
[
'label' => 'Status',
'format' => 'raw',
'value' => function ($data) {
if ($data->deactive == 0) {
return Html::a(FA::i('circle'), ['agency/change-status', 'id' => $data->member_id, 'set' => 1], ['onclick' => "return confirm('Deactive this state/site?');", 'class' => 'status-inactive']);
} else {
return Html::a(FA::i('circle'), ['agency/change-status', 'id' => $data->member_id, 'set' => 0], ['onclick' => "return confirm('Active this state/site?');", 'class' => 'status-active']);
}
},
],
]);
<?php Pjax::end(); ?>
actionChangeStatus() is as below:
public function actionChangeStatus($id, $set) {
if (!empty($id) && isset($set)) {
$localGovt = $this->findModel($id);
$localGovt->deactive = $set;
if ($localGovt->save()) {
Yii::$app->getSession()->setFlash('success-status', 'State Status Changed');
} else {
Yii::$app->getSession()->setFlash('error-status', 'There is some error. Please consult with Admin.');
}
$searchModel = new AgencySearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider
]);
}
}
Note: I need 'enablePushState' => true for other events, so I can't change it to false inside Pjax::begin
I believe it's
'enableReplaceState' => true
Pass this attribute to Pjax:
Pjax::begin(['enablePushState' => false]);
This worked for me.

Trying to get property of non-object while using kartik-v for image uploading in Yii2

I'm using yii2-widget-fileinput for an image uploading in a form.
When I click on upload or the create button I get Trying to get property of non-object error in controller.
Controller
public function actionCreate()
{
Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/uploads/';
$model = new Ads();
$provinces = ArrayHelper::map(Province::find()->all(), 'name', 'name');
if ($model->load(Yii::$app->request->post())){
$image = UploadedFile::getInstances($model, 'image');
$model->filename = $image->name;
$ext = end((explode(".", $image->name)));
$avatar = Yii::$app->security->generateRandomString().".{$ext}";
$path = Yii::$app->params['uploadPath'].$avatar;
if ($model->save()) {
$image->saveAs($path);
$model->image_adr = $path;
return $this->redirect(['view', 'id' => $model->id]);
}else{
echo "error on saving the model";
}
}
return $this->render('create', [
'model' => $model,
'provinces'=>$provinces,
]);
}
model rules
public function rules()
{
return [
[['type', 'explanation', 'cost', 'province_name', 'address'], 'required'],
[['type', 'explanation', 'image_adr', 'address'], 'string'],
[['cost'], 'integer'],
[['province_name'], 'string', 'max' => 20],
[['province_name'], 'exist', 'skipOnError' => true, 'targetClass' => Province::className(), 'targetAttribute' => ['province_name' => 'name']],
[['image'],'safe'],
[['image'], 'file', 'extensions'=>'jpg, gif, png', 'maxFiles'=>3,],
];
and finnally the view
<?= $form->field($model, 'image[]')->widget(FileInput::classname(), [
'options'=>['accept'=>'image/*', 'multiple'=>true],
'pluginOptions'=>['allowedFileExtensions'=>['jpg','gif','png'], 'overwriteInitial'=>false,]
]); ?>
the problem should refer to this part in the controller I think
$image = UploadedFile::getInstances($model, 'image');
An image of the error might be helpful
You should check first is image in post or not.
....
$image = UploadedFile::getInstances($model, 'image'); //getInstanceByName
if (!empty($image))
$model->filename = $image->name;
.....
if ($model->save()) {
if (!empty($image))
$image->saveAs($path);
.........
Make sure in your form ency type is added:
$form = ActiveForm::begin([
'id' => 'form_id',
'options' => [
'class' => 'form_class',
'enctype' => 'multipart/form-data',
],
]);
The problem is when you're using UploadedFile::getInstances($model, 'image'); you should work with foreach or treat it like an array.
Something that made me a problem was that even if you're using UploadedFile::getInstanc (notice the obsoleted s in the end) you should still treat it like an array and in all parts you should use $image[0], not $iamge lonely.

Yii2 Confirm Password not working

I am trying to build a signup form, it works fine when I dont use repeat password, it saves to the model, but when I use my repeat password it just does'nt let me save them in the database. My code is below.
SimUser.php file
public function rules()
{
return [
[['user_email', 'user_password_hash','company_id','user_fname', 'user_lname','agree'], 'required'],
['agree','required','requiredValue' => 1, 'message' => ''],
['user_password_hash_repeat', 'compare','compareAttribute' => 'user_password_hash','message' => 'Password don\'t match'],
[['agree'],'safe'],
[['user_password_hash_repeat'],'safe'],
[['user_company', 'user_suspended', 'user_deleted'], 'integer'],
[['user_created'], 'safe'],
[['user_email'], 'string', 'max' => 255],
[['user_password_hash'], 'string', 'max' => 72],
[['user_fname', 'user_lname'], 'string', 'max' => 45],
[['user_auth_key'], 'string', 'max' => 32],
[['user_access_token'], 'string', 'max' => 100],
];
}
My controller action: site/signup
public function actionSignup()
{
$company = new Company();
$company->load(Yii::$app->request->post());
$company->save();
$model = new SimUser();
if ($model->load(Yii::$app->request->post())) {
$model->setPassword($model->user_password_hash);
$model->generateAuthKey();
$model->company_id = $company->company_id;
//var_dump($model); exit();
$model->save();
$model = new LoginForm();
return $this->render('login',[
'model' => $model,
]);
}
return $this->render('signup', [
'model' => $model,
'company' => $company,
]);
}
Here I am saving the comany name in the company model and the others in the user table.
My views file: signup.php
<h1>Sign Up</h1>
<?= $form->field($model, 'user_fname')->textInput(['placeholder'=>'First Name*','class'=>'form-control col-lg-4'])->label(false);?>
<?= $form->field($model, 'user_lname')->textInput(['placeholder'=>'Last Name*','class'=>'form-control col-lg-4'])->label(false); ?>
<?= $form->field($model,'user_email')->textInput(['placeholder'=>'Email*','class'=>'form-control col-lg-4'])->label(false); ?>
<?= $form->field($model, 'user_password_hash')->passwordInput(['placeholder'=>'Password'])->label(false); ?>
<?= $form->field($model, 'user_password_hash_repeat')->passwordInput(['placeholder'=>'Confirm Password*','class'=>'form-control col-lg-4'])->label(false); ?>
<?= $form->field($company, 'company_name')->textInput(['placeholder'=>'Company Name*','class'=>'form-control col-lg-4'])->label(false); ?>
<?php echo $form->field($model, 'agree')->checkbox(); ?>
<div class="form-group">
<?= Html::submitButton('Sign Up', ['class' => 'pull-left padding-0 btn btn-success', 'name' => 'signup-button']) ?>
</div>
The error message for the company doesn't go, it is always there.. attached output as image
Can anyone of you help me solve this issue? Thanks in advance!!
Company.php
*/
public function rules()
{
return [
[['company_name'], 'required'],
[['company_name'], 'string', 'max' => 75],
];
}
In the controller have saved Company in the beginnig itself. So everytime, I load the page It is saving before I could submit it. Hence the error remains as it is.
Code to be changed:
$company = new Company();
$model = new SimUser(['scenario' => SimUser::SCENARIO_REGISTER]);
if ($model->load(Yii::$app->request->post()) && $company->load(Yii::$app->request->post())) {
$company->save();
$model->setPassword($model->user_password_hash);
$model->generateAuthKey();
$model->company_id = $company->company_id;
$model->save();
So 1 issue has been solved.. Unable to solve the confirm password issue! Would be helpful if someone can post what the mistake is?

Updating Image in Yii2

While updating image using Yii2 I'm facing a problem with the validation.Its always asking me to upload an image. But I don't want this. Always updating an image is not necessary.
I tried skipOnEmpty but its not working properly it cause effect while uploading a photo, which is also incorrect.
Please help!!
Model
public function rules()
{
return [
[['carid', 'name'], 'required'],
[['carid', 'coverphoto', 'status'], 'integer'],
[['name'], 'string', 'max' => 200],
[['imageFiles'], 'image','extensions' => 'png, jpg, jpeg, gif', 'maxFiles' => 4, 'minWidth' => 100, 'maxWidth' => 800, 'minHeight' => 100, 'maxHeight'=>600,'skipOnEmpty' => true],
];
}
Controller
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->photoid]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
You should to use scenario for update.
Like as,
Add on condition in model's rule for applying scenario .
[['imageFiles'], 'image','extensions' => 'png, jpg, jpeg, gif', 'maxFiles' => 4, 'minWidth' => 100, 'maxWidth' => 800, 'minHeight' => 100, 'maxHeight'=>600,'skipOnEmpty' => true, 'on' => 'update-photo-upload'],
And use that scenario in controller's action.
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->scenario = 'update-photo-upload';
........
.....
}
try rule as
[
['imageFiles'], 'file',
'extensions' => 'png, jpg, jpeg, gif',
'mimeTypes' => 'image/jpeg, image/png',
'maxFiles' => 4,
'minWidth' => 100,
'maxWidth' => 800,
'minHeight' => 100,
'maxHeight'=>600,
'skipOnEmpty' => true
],
This is working in my case, hope it works for you too.
**Your View Like This**
<?php use yii\widgets\ActiveForm;?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'imageFiles')->fileInput() ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end() ?>
*** Your Controller Like This******
use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;
class SiteController extends Controller
{
public function actionUpdate()
{
$model = new UploadForm ();
$model->scenario = 'update';
if (Yii::$app->request->isPost) {
$model->imageFiles= UploadedFile::getInstance($model, 'imageFiles');
if ($model->upload()) {
// file is uploaded successfully
return;
}
}
return $this->render('update', ['model' => $model]);
}
}
***** Your ModelLike This ******
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
/**
* #var UploadedFile[]
*/
public $imageFiles;
public function rules()
{
return [
[['carid', 'name'], 'required'],
[['carid', 'coverphoto', 'status'], 'integer'],
[['name'], 'string', 'max' => 200],
[['imageFiles'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg', 'maxFiles' => 4,'on'=>'update'],
];
}
public function upload()
{
if ($this->validate()) {
foreach ($this->imageFiles as $file) {
$file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
}
return true;
} else {
return false;
}
}
function scenario()
{
return [
'create' => ['imageFiles ', 'carid','name','coverphoto','status'],
'update' => ['imageFiles ', 'carid','name','coverphoto','status'],
];
}
}