Conditional validation if input field is empty or not? - yii2

I have form which contain address, country, district field. If address is not empty then country and district is required. If address is empty then country, district not required.
I define in table model rules method like this using conditional validation as document says
public function rules()
{
return [
[['username', 'password', 'email', 'tanggal_daftar','password_validate'], 'required'],
[['customer_id','propinsi_id', 'kota_id', 'kecamatan_id', 'user_status_id','poin'], 'integer'],
[['tanggal_daftar','mobile_token','fb_id','newsletter','agree','password_validate','old_password'], 'safe'],
[['username', 'jenis_kelamin'], 'string', 'max' => 10],
[['password'], 'string', 'max' => 70],
[['identitas'], 'required', 'on' => 'login'],
[['email','username'], 'unique','except' => 'login'],
[['email'],'email'],
[['nama', 'hobby', 'pekerjaan'], 'string', 'max' => 30],
//address field
[['alamat'], 'string', 'max' => 200],
//country field
[['negara_id'], 'string', 'max' => 3],
[['kode_pos'], 'string', 'max' => 6],
[['hp'], 'string', 'max' => 18],
[['is_agent'],'boolean'],
[['profile_picture'],'string','max' => 100],
[['password_validate'], 'compare', 'compareAttribute'=>'password', 'message'=>Yii::t('app', 'Password tidak sama')],
[['agree'],'compare','operator' => '==','compareValue' => true,'message' => ''],
//country field
[['country_id'], 'required', 'when' => function($model){
return $model->address != null;
..
what about the code if address is empty then country not required??
}],
My view
...
...
.. address field ..
<?= $form->field($model, 'alamat')->textInput(['maxlength' => true,'class'=>'input_text'])->label('Address')?>
... country field drop down ..
<?= $form->field($model, 'negara_id')->dropDownList(ArrayHelper::map(TbNegara::find()->all(), 'negara_id', 'negara_name'),['prompt'=>'-- Pilih Negara --','id'=>'negara_id','class'=>'input_select'])->label('Country') ?>
...
...
If I test above code, whether address empty or not in my form then country field always required.
Am I doing wrong?
UPDATED
country is required when address is not null is working now.
so if I type in address field and press submit button it show required error, then if I type nothing in adress field and press submit button, it will process the submit.
Solution is
without 'enableAjaxValidation' => true, at begin form
and here is my table model rules for country field
[['negara_id'], 'required', 'when' => function($model){
return $model->alamat != null;
}, 'whenClient' => "function (attribute, value){
return $('#tbcustomer-alamat').val() != '';
}"],
now I have other similar problem when I implement this code
[['propinsi_id'], 'required', 'when' => function($model){
//district required if country is set
return $model->negara_id != null;
}, 'whenClient' => "function (attribute, value){
return $('#negara_id').val() != '';
}"],
district is not required even country is set, it should required if country set.
so If I type in address and set country, and leave district blank and I press submit, it will process submit but resulting in district cann't be blank [ 'propinsi_id' => [ 0 => 'ID Propinsi cannot be blank.' ] ]
something like my validation work on server side but not in client side.
district loaded via ajax when country is set
here is view for district field
<div class="form_grup leftside fl">
<div class="input_select">
<?php
if (isset($model->propinsi)){
echo $form->field($model, 'propinsi_id')->widget(DepDrop::classname(), [
'options'=>['id'=>'propinsi_id','class'=>'input_select'],
'data'=>[$model->propinsi_id=>$model->propinsi->propinsi_name],
'pluginOptions'=>[
'initialize' => true,
//depends on country
'depends'=>['negara_id'],
'class'=>'input_select',
'placeholder'=>'-- Pilih Propinsi --',
'url'=>Url::to(['customer2/propinsi'])
]
]);
} else {
echo $form->field($model, 'propinsi_id')->widget(DepDrop::classname(), [
'options'=>['id'=>'propinsi_id','class'=>'input_select'],
'pluginOptions'=>[
'initialize' => true,
//depends on country
'depends'=>['negara_id'],
'class'=>'input_select',
'placeholder'=>'-- Pilih Propinsi --',
'url'=>Url::to(['customer2/propinsi'])
]
]);
}
?>
<!-- <i class="fa fa-angle-down"></i> -->
</div>
</div>
what am I doing wrong for district field client side validation?

_form.php
<?php $form = ActiveForm::begin(['enableAjaxValidation' => true]); ?>
controller
if ($model->load(Yii::$app->request->post()) && Yii::$app->request->isAjax) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return \yii\widgets\ActiveForm::validate($model);
}
model
[['country_id'], 'required', 'when' => function ($model) { return $model->address != null;}, 'enableClientValidation' => false ],
[['propinsi_id'], 'required', 'when' => function ($model) { return $model->country_id != null;}, 'enableClientValidation' => false ],

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'];
}
)

Yii2 client side validation refreshes the page on form submit

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
]) ?>

How to populate saved multiple values from junction table into dropdown in YII2?

I got an error message, when i want to load back saved elements on update form.
Controller
$contentCategory = ContentCategory::find()
->where(['content_id' => $id])->all();
View
<?= $form->field($contentCategory, 'category_id')
->dropdownList(ArrayHelper::map(Category::find()->all(),'id','title'),
['prompt'=>'Select Category', 'multiple' => 'multiple']
)->label('Add categories'); ?>
The error message.
Call to a member function isAttributeRequired() on array
If i change the all() method to one() it's works but select only one element (of course).
Update:
#scaisEdge I'm using a content_category junction table to insert relations contents with categories.
content_id category_id
1 2
1 3
Model
public function rules()
{
return [
[['content_id', 'category_id'], 'integer'],
[['category_id'], 'exist', 'skipOnError' => true, 'targetClass' => Category::className(), 'targetAttribute' => ['category_id' => 'id']],
[['content_id'], 'exist', 'skipOnError' => true, 'targetClass' => Content::className(), 'targetAttribute' => ['content_id' => 'id']],
];
}
The trouble in that you use $contentCategory array of founded models as form field model.
I think you should just change $contentCategory variable from your view on your certain model like $model = ContentCategory::findOne($id);
#Csaba Faragó
$arr = array();
$colorarr=array();
foreach ($detmodel as $key => $detailm){
//$detailm;
$id = $detailm['productid'];
$sid = $detailm['sizeid'];
$sidex= explode(",",$sid);
$i = 0;
foreach($sidex as $size_id)
{
$val = $sidex[$i];
$val = (int)$val;
array_push($arr, $val);
$i++;
}
<?php $sizelist = ArrayHelper::map(Size::find()->all(),'id','size');
// $idd = '4';
?>
<?php
$detailm->sizeid = $arr;
// print_r($detailm->sizeid);
?>
<?= $form->field($detailm, 'sizeid')->widget(Select2::classname(), [
'data' => $sizelist,
'language' => 'de',
'options' => ['placeholder' => 'Select sizes ...','multiple' => true],
'pluginOptions' => [
'tags' => true,
'tokenSeparators' => [',', ' '],
'maximumInputLength' => 10
],
]);
?>
do all this in view page
I have found a solution here. He is perfectly solve my issue.

Yii2 Kartik Select2 Multiple Tags Input String Error

I used Select2 widget to store selected tags input to MySQL database. I'am expecting something like 010102, 010103, 010299 to be stored in the database table.
Here is the view.php
echo $form->field($model, 'SpField')->label(false)->widget(Select2::className(), [
'data' => ArrayHelper::map(Supplierfield::find()->all(), 'sfCode', 'sfCode'),
'options' => [
'multiple' => true,
'placeholder' => 'Choose tag ...',
],
'pluginOptions' => [
'tags' => true
]
]);
UPDATED : Here is the corresponding rules on the model
public function rules()
{
return [
[['spCode', 'SpName','SpPhone', 'SpEmail', 'SpAddress', 'SpPostcode', 'SpTown', 'SpState', 'SpDistrict','SpBumi', 'SpStatus'], 'required'],
[['RecordStamp','SpField'], 'safe'],
[['spCode'], 'string', 'max' => 7],
[['SpName', 'SpEmail'], 'string', 'max' => 50],
[['SpPhone'], 'string', 'max' => 20],
[['SpAddress'], 'string', 'max' => 100],
[['SpPostcode'], 'string', 'max' => 5],
[['SpTown', 'SpState'], 'string', 'max' => 30],
[['SpBumi', 'SpStatus'], 'string', 'max' => 15],
[['SpDistrict'], 'string', 'max' => 50],
[['spbalance','spfloatbalance'], 'number'],
[['SpField'], 'string', 'max' => 255, 'message' => 'Field must be a string'],
[['spCode'], 'unique'],
];
}
but, why am I getting this error. It says that the input field must be a string.
FYI : SpField is varchar(255)'s field and sfCode is varchar(10)'s field.
Any help is much appreciated.
This is what I've done as suggested by #HasiburRahman.
1. Eliminate the string validation rule in model Supplier because the widget input is in array form and not string.
[['SpField'], 'string', 'max' => 255, 'message' => 'Field must be a string'],
2. Convert the input into string using json_encode() and save it in the controller.
if ($model->load(Yii::$app->request->post()) && $model->save())
{
$model->SpField = json_encode(Yii::$app->request->post( 'Supplier' )['SpField']); //convert the array into string
$model->save();
}
You may use json_decode() to convert it back to array to display $data using the Select2 widget. In my case
it look something like this $data = json_decode($model->SpField);
For a newbie like me, this work very well. Hope this will help others too.
implode the input with coma value and blankspace
", "
for query to the db.
public function actionCreateOrUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$model->SpField = implode (", ",$model->SpField);
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create_or_update', [
'model' => $model,
]);
}
}

Yii2 DateControl: How to set default value (date)

I have in views/example/_form.php the following date field:
use yii\widgets\ActiveForm;
use kartik\datecontrol\DateControl;
...
$form = ActiveForm::begin();
...
echo $form->field($model, 'date')->widget(DateControl::className(), [
'type' => DateControl::FORMAT_DATE,
// 'value' => date('Y-m-d'),
// 'value' => date('d.m.Y'),
// 'value' => time(),
// 'value' => '02.12.2015',
// 'value' => '2015-12-02',
// 'value' => '2015-12-02 00:00:00 0000',
// 'value' => date('Y-M-d'),
// 'value' => date('d.M.Y'),
// 'value' => date('dd.MM.yyyy'),
]);
...
ActiveForm::end();
None of my attempts to set the default date was successfull (see the commented lines above). I have always received no error message and no default value. The resulting HTML input field looks always the same (the 'value' is empty):
<input type="text" id="yiiversion-date-disp" class="form-control" name="date-yiiversion-date" value="" data-krajee-datecontrol="datecontrol_1e107159" data-datepicker-source="yiiversion- date-disp-kvdate" data-datepicker-type="2" data-krajee-kvdatepicker="kvDatepicker_0aa71c62">
Configuration in config/main.php looks like this:
'modules' => [
'datecontrol' => [
'class' => 'kartik\datecontrol\Module',
'autoWidget' => true,
'autoWidgetSettings' => [
'date' => [
'pluginOptions' => [
'autoclose' => true,
'todayHighlight' => true,
'todayBtn' => true,
],
],
],
],
],
The dates are displayed as 01.01.2015 ('dd.MM.yyyy') and saved as 2015-01-01 ('Y-M-d') - MySQL datatype DATE.
More information:
https://github.com/kartik-v/yii2-datecontrol
http://demos.krajee.com/datecontrol
As suggested by InsaneSkull the solution is quite simple. I had to add to the correspondig controller only: $model->date = date('Y-m-d');
The resulting action could look e.g. like this:
public function actionCreate()
{
$model = new YiiTask();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
$model->date = date('Y-m-d');
return $this->render('create', [
'model' => $model,
]);
}
}