Yii2 When Validation - yii2

Out of two pairs of input fields I only need one or the other. I can't get the validation right.
listing_image_url and poster_image_url should only be required if $model->listingImage is null.
Also tried using strlen($model->listingImage) == 0.
[['listing_image_url', 'poster_image_url'], 'required',
'when' => function($model){
var_dump($model->listingImage); //result is empty string '0'
return $model->listingImage == NULL && $model->posterImage == NULL;
},'whenClient' => "function(attribute, value) {
return $('#vod-listingimage').val() == '' && $('#vod-posterimage').val() == '';
}", 'message' => 'look'
],
Just as above but the other way around.
[['listingImage', 'posterImage'], 'required',
'when' => function($model) {
return $model->listing_image_url == NULL && $model->poster_image_url == NULL;
},
'whenClient' => "function(attribute, value) {
return $('#vod-listing_image_url').val() == '' && $('#vod-poster_image_url').val() == '';
}", 'message' => 'hi'
],

You could create your own inline validator for the model validation on backend side, like this:
[['listingImage', 'posterImage'], function($attribute, $params) {
if ($this->listingImage === null && empty($this->$attribute)) {
$this->addError($attribute, 'Can not be blank if listingImage is null');
}
}]
In order to also provide the client side validation you can build a custom standalone validator.

I tried myself something similar and the behavior is odd indeed.
But you can create a validator that checks if only one of the two fields is selected.
public function validateListingAgainstPoster($attribute, $params)
{
if (!empty($this->listing_image_url) && !empty($this->poster_image_url)) {
$this->addError($attribute, 'Only one of "Listing" or "Poster" fields can be selected.');
}
if (empty($this->listing_image_url) && empty($this->poster_image_url)) {
$this->addError($attribute, 'Please select one of "Listing" or "Poster Group".');
}
}
And in your rules:
[['listing_image_url', 'poster_image_url'], 'validateListingAgainstPoster', 'skipOnEmpty' => false, 'skipOnError' => false],

Related

Yii2 : Setting Access Control matchcallback

I just want to know if I can do this so I dont have to repeat the same code over and over
[
'allow' => true,
'actions' => ['index', 'update', 'view', 'logout'],
'roles' => ['#'],
'matchCallback' => function(){
return (Yii::$app->user->identity->team_id == '47' && Yii::$app->user->identity->team_id == '62'
&& Yii::$app->user->identity->team_id == '63' && Yii::$app->user->identity->team_id == '64'
&& Yii::$app->user->identity->team_id == '65' && Yii::$app->user->identity->team_id == '66' && Yii::$app->user->identity->role_id == '1');
}
],
Or something similar to that.
Thank you
First, I don't understand why you are using && instead of ||. Is it a typo?
Now for answering the question, I think it will be better for example to create a function for that purpose in the Model representing your identity like below: (I am sure you will need it later somewhere else)
public function belongsToGroup()
{
if( $this->team_id == '47'
|| $this->team_id == '62'
...
&& $this->role_id == '1' ){
return true;
} else {
return false;
}
}
And then just call your function in the authorisation control:
[
'allow' => true,
'actions' => ['index', 'update', 'view', 'logout'],
'roles' => ['#'],
'matchCallback' => function($rule, $action){
return Yii::$app->user->identity->belongsToGroup();
}
],

Filter a gridview column that is processed by a function in yii2

I have a column named wp_status. If person A, person B, person C, person D approves a work, the value of column wp_status will be changed to Approved, else the value will be as it is in the database - Assigned.
The code to change the value dynamically in the gridview is -
[
'label' => 'Status',
'attribute'=>'wp_status',
'value' => function ($model) {
return $model->Status();
}
],
And the function Status in model Workpermit is -
public function Status()
{
//$data = Workpermit::findOne($this->id);
$total = $this->wp_status;
if($this->wp_type == 'Safe Work Permit' && $this->wp_apoapproval == 'Approved' && $this->wp_spsapproval == 'Approved' && $this->wp_officerapproval == 'Approved'){
$total = 'Approved';
}
return $total;
}
This works fine so far. But I'm not sure how to filter it with Kartik Select2 widget. I tried like following -
[
'label' => 'Status',
'attribute'=>'wp_status',
'filterType'=>GridView::FILTER_SELECT2,
'filter'=>ArrayHelper::map(Workpermit::Status()->asArray()->all(), 'total', 'total'),
'filterWidgetOptions'=>[
'pluginOptions'=>['allowClear'=>true],
],
'filterInputOptions'=>['placeholder'=>'Permit Status'],
'value' => function ($model) {
return $model->Status();
}
],
And here I'm getting error - Using $this when not in object context
could be uisng a getter
public function getStatus()
{
//$data = Workpermit::findOne($this->id);
$total = $this->wp_status;
if($this->wp_type == 'Safe Work Permit' && $this->wp_apoapproval == 'Approved' && $this->wp_spsapproval == 'Approved' && $this->wp_officerapproval == 'Approved'){
$total = 'Approved';
}
return $total;
}
the call $model->status (status lowercase)
[
'label' => 'Status',
'attribute'=>'wp_status',
'value' => function ($model) {
return $model->status;
}
],

Yii2 : - Require one error message for three fields

I have three dropdowns for day, month, and year. when I applied required condition yii2 validation show individual error for all three fields. But I want single error message for three fields like "dob is required".
view file :
<?= $form->field($model, "month")->dropDownList([], ['class'=>'form-control day'])->label(false);?>
<?= $form->field($model, "day")->dropDownList([], ['class'=>'form-control day'])->label(false);?>
<?= $form->field($model, "year")->dropDownList([], ['class'=>'form-control year'])->label(false);?>
model :
public $day;
public $month;
public $year;
[['month','day','year'], 'required', 'when' => function ($model) {
return (($model->month == "") || ($model->day == "") || ($model->year == ""));
},
'whenClient' => "function (attribute, value) {
return ($('#user-month').val() == '' || $('#user-day').val() == '' || $('#user-year').val() == '');
}",'on'=>'profile'
]
This code showing me error messages for all three dropdowns individually. But i want single error message for dob: like "dob is required".
Try this :
Write this code in your Model :
public function rules()
{
return [
[['month','day','year',],'required','on'=>['create','update'],'message' => 'Please enter DOB.'],
];
}
Write this code in your Action in Controller where you call your view:
$model = new YourModelName();
$model->scenario = "create";
Example :
$model = new User();
$model->scenario = "create";
Maybe You sholud do something more like:
['month', 'validationFunction', 'skipOnEmpty' => false]
...
public function validationFunction($attribute, $params) {
if( !$this->hasErrors() ) {
if (!$this->month || !$this->day || !$this->year) {
$this->addError($attribute, 'dob is required');
}
}
}

yii2 disable the rules if a checkbox is selected

In the active form, I have 3 textinput and one checkbox.
All the 3 textinputs have rules that says cannot be empty. What I want is if the checkbox is clicked, It will disable the rules and will save the empty record in the database.
here is screen shot of the active form..
You could define the rules that way (using when):
public function rules()
{
return [
['cancelled', 'boolean'],
['checkNumber', 'required'],
['payee', 'required', 'when' => function ($model) {return !$model->cancelled;}],
['particulars', 'required', 'when' => function ($model) {return !$model->cancelled;}],
];
}
You may want to add whenClient as well to let the browser check this before it submits the form.
You can do something like this:
$model = new SomeForm();
if ($model->load(Yii::$app->request->post())){
if ($model->checkbox == true) $model->scenario = 'checked';
}
// your model rules:
[['name', 'email', 'subject', 'body'], 'safe', 'on' => 'checked']
or alternatively You can do this:
if ($model->checkbox == true) $model->save(false); //this will disable any validation so be carefull
edit:
if You need cliend side validation switch, You have to use this:
[['name', 'email', 'subject', 'body'], 'required', 'when' => function ($model) {
return $model->cancelled == '0';
}, 'whenClient' => new JsExpression("function (attribute, value) { return $('#mailform-cancelled').val() == '0';}")]

JSON response always returns true

I have problem with resolving my response which always resolve as true. I am submitting a form for forgotten password, and i have only one field there, that is e-mail. I check in the database for the record on base on the e-mail, and if the record is returned, i set the json to true, else to false. Here is the code from my Codeigniter controller:
public function checkEmail()
{
// set the validation rules
$this->form_validation->set_rules('checkemail', 'E-Mail', 'valid_email');
$this->form_validation->set_error_delimiters('<br /><p class=jsdiserr>', '</p><br />');
// if validation is passed
if ($this->form_validation->run() != FALSE)
{
$ids=array();
$ids[0]=$this->db->where('email', $this->input->post('checkemail'));
$query = $this->backOfficeUsersModel->get();
if($query)
{
$data = array(
'userid' => $query[0]['userid'],
'username' => $query[0]['username'],
'password' => $query[0]['password'],
'firstname' => $query[0]['firstname'],
'lastname' => $query[0]['lastname'],
'email' => $query[0]['email']
);
$currentUser = array();
$currentUser = $this->session->set_userdata($data);
echo json_encode(array("success" => "true"));
} else {
echo json_encode(array("success" => "false"));
}
// form validation has failed
} else {
$errorMessage = "Wrong email!";
}
} // end of function checkEmail
Now, when i check the result in my javascript file, i get always true. Here is the code:
$("#formSendPassword").submit(function(e){
e.preventDefault();
var email = $(this).find("#checkemail").val();
var obj = {email: email};
var url = $(this).attr("action");
$.post(url, obj, function(r){
if(r.success == "true") {
console.log(r.success);
$('#forgotPasswordForm').hide();
$('#successMailMessage').fadeIn()
} else {
$('#forgotPasswordForm').hide();
$('#errorMailMessage').fadeIn()
}
}, 'json')
})
Can anyone give me a hand with this?
Regards,Zoran
Firstly modify the PHP...
json_encode(array("success" => "true"));
to
json_encode(array("success" => true));
and also
json_encode(array("success" => "false"));
to
json_encode(array("success" => false));
Then modify the JS as follows by changing...
if(r.success == "true") {
to...
if(r.success === true) {
See how you go from there!
EDIT: In liaison with the OP we concluded that the actual issue was the way JS was posting the data.
var obj = {email: email};
Should have been...
var obj = {checkemail: email};
There were also a few specific problems with the PHP that were unrelated to the issue but have now been fixed.
if ($this->form_validation->run() != FALSE)
should be
if ($this->form_validation->run() !== FALSE)
or simply
if (!$this->form_validation->run())
Is the best way to chekc for false... != may not always do as you expect!
You need to parse the JSON in the JS: myObj = $.parseJSON(r);
then use myObj.success