yii2 ajax validation error in widget, yii\web\Response - php

I'm getting error from yii\web\Response when I use ajax validation.
Object of class yii\web\Response could not be converted to string
widget:
public function run()
{
$model = new Participants();
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())) {
$list = implode( ", ",$model->sections);
$model->sections = $list;
$model->save();
Yii::$app->session->setFlash(Alert::TYPE_SUCCESS, [
[
'title' => 'Congratulations!',
'text' => 'You are registered on the forum. Check out your email to get news about forum.',
'confirmButtonText' => 'Done!',
]
]);
return Yii::$app->controller->redirect(Yii::$app->request->referrer ?: Yii::$app->homeUrl);
}
return $this->render('header', [
'model' => $model,
]);
}
view of widget:
<?php $form = ActiveForm::begin();?>
...
<?= $form->field($model, 'email', ['enableAjaxValidation' => true])->textInput(['placeholder' => 'Email']); ?>
how I can solve this error? P.S. yii version - 2.0.17-dev

\yii\base\Widget::run() must return a string (all widgets basically)
All you should do within method run() is output or render content and you're attempting to return a Response object by way of return ActiveForm::validate($model); and return Yii::$app->controller->redirect(..)
i suggest you move all the code that supposed to handle form submission to it's own action
SiteController extends controller {
public function actionRegisterParticipant {
$model = new Participants();
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())) {
$list = implode(", ", $model->sections);
$model->sections = $list;
$model->save();
Yii::$app->session->setFlash(Alert::TYPE_SUCCESS, [
[
'title' => 'Congratulations!',
'text' => 'You are registered on the forum. Check out your email to get news about forum.',
'confirmButtonText' => 'Done!',
]
]);
return Yii::$app->controller->redirect(Yii::$app->request->referrer ?: Yii::$app->homeUrl);
}
// ...
}
and the form in the widget view should always point to this action:
<?php $form = ActiveForm::begin(['action' => 'site/register-participant']);?>
...
<?= $form->field($model, 'email', ['enableAjaxValidation' => true])->textInput(['placeholder' => 'Email']); ?>

Widget should return string as a result, but return Yii::$app->controller->redirect() returns Response object with configured redirection. If you want to redirect inside of widget you should use something like that:
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->controller->asJson(ActiveForm::validate($model));
Yii::$app->end();
}
// ...
Yii::$app->session->setFlash(/* ... */);
Yii::$app->controller->redirect(Yii::$app->request->referrer ?: Yii::$app->homeUrl);
Yii::$app->end();
But this smells like a bad design - widget should not be responsible for controlling application flow. It is better to handle user input in regular action/controller.

Related

How to deal with conditioned based validation in laravel?

I have a situation and unfortunately not sure how to sort it out in proper way. I have below script
$validator = Validator::make(
$request->all(),
[
'game_id' => 'required|integer'
],
$messages
);
if ($validator->fails()) {
$response = $validator->messages();
}else{
$response = $gameService->setStatus($request);
}
Now each game has different type, I wanted to add validation on behalf of type. For example if a game is Task Based then I would add validation for time which would be mandatory only for Task based game otherwise it would be an optional for other types.
I have three types of games
1 - level_based
2 - task_based
3 - time_based
In the type table, each game has type.
So is there any way to add validation? I want to do it, inside validation function.
Thank you so much.
You can write your conditions before the validation.
$data = $request->all();
if ($data['game_id'] == 1) {
$rules = [
// level_based validation
];
} else if($data['game_id'] == 2) {
$rules = [
// task_based validation
];
} else {
$rules = [
// time_based validation
];
}
$validator = Validator::make($data, $rules);
Hope it helps. Cheers.
I would go with the required_if validation rule.
So in your case, will send two fields, the type can be a hidden field for example, then on the game_id you will add
'game_id' => 'required_if:type,1'
and so on.. And of course you can customize the error messages.
Try this code snippet
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class CreateGameRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
try {
$request = $this->request->all();
$rule_array = collect();
$rule1 = [
'game_id' => 'required|integer'
]
$rule_array = $rule_array->merge($rule1);
if(isset($request->task_id))
{
$rule2 = [
'task_id' => 'required|integer'
]
}
$rule_array = $rule_array->merge($rule2);
return $rule_array->all();
} catch (Exception $e) {
return $e;
}
}
public function messages(){
return [
'game_id' => 'Please select valid game',
'task_id' => 'Please select valid task'
];
}
}
then invoke this request class in controller function as
use App\Http\Requests\CreateGameRequest;
public function game(CreateGameRequest $request)
{
}

yii2 conditional validation on server side

I have one form that form have below fields
i)Book
ii)Amount
Controller action:
public function actionBook()
{
$model = new Book();
if ($model->load(Yii::$app->request->post()) && $model->validate()){
print_r($model);exit;
return $this->redirect('/Book');
}
$model->getBook();
return $this->render('BookForm', ['model' => $model]);
}
Whenever this page will load i will call one model function by default, the function is getBook()
Model:
public book;
public amount;
public showAmountField;
public function rules()
{
return [
[['book'], 'required'],
['amount', 'required', 'when' => function($model) {
return $model->showAmountField == true;
}],
];
}
public function getBook()
{
if(some condition here){
$this->showAmountField = true;
}
}
so whenever the showAmountField is true at the time the amount field is required, otherwise it will not required, here all are working fine and the client side validation also working fine, but when i change amount field id using console(f12) at the time the server side validation not working and form is simply submit with the amount field is empty, so what is wrong here. Please explain anyone.
UPDATE
View
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->params['breadcrumb'] = $model->breadCrumbs;
?>
<?php $form = ActiveForm::begin([
'id' => 'book-form',
'options' => ['class' => 'form-horizontal'],
]);
?>
<?= $form->field($model, 'book')->textInput()->label("Book"); ?>
<?php if($model->showAmountField): ?>
<?= $form->field($model, 'amount')->textInput()->label("Amount"); ?>
<?php endif; ?>
<?= $form->errorSummary($model, ['header' => '']); ?>
<?php ActiveForm::end(); ?>
Validation occurs on the field ID, if you change it through the console, the model does not understand that it needs to validate
$model = new Book();
if ($model->load(Yii::$app->request->post()) && $model->validate()){
print_r($model);exit;
return $this->redirect('/Book');
}
$model->getBook();
here you are initialising the $model->getBook(); after the if block so the model gets overridden in post request with new instance and hence server side validations fails for when condition.
$model = new Book();
$model->getBook();
if ($model->load(Yii::$app->request->post()) && $model->validate()){
print_r($model);exit;
return $this->redirect('/Book');
}
it should be before post load

Yii2 validation class ip does not exist

I have install Yii2-basic framwork and i want to validate inputform allowed:
http://www.yiiframework.com/doc-2.0/guide-tutorial-core-validators.html
Email, string validation all work well, but if i use IP validation, my Aplication throw error Class ip does not exist.
There is my code:
Model:
public function rules() {
return [
[['name','ipadress'],'required'],
['ipadress','ip']
];
}
There is my controller:
public function actionIndex()
{
$model= new Router();
if($model->load(Yii::$app->request->post()) && $model->validate()){
Yii::$app->session->setFlash('success','WORK WELL');
} else {
$error= $model->errors;
}
return $this->render('index', [
'list' => $list,
'menu' => $menu->getMenu(),
'model'=>$model,]);
}
And my View
$form = ActiveForm::begin();
echo $form->field($model,'name');
echo $form->field($model,'ipadress');
?>
<?= Html::submitButton('Submit',['class'=>'btn btn-success']); ?>
If i try validate email in rules, all works well:
return [
[['name','ipadress'],'required'],
['ipadress','email']
];
Please can somebody help with this problem ?
Thank you in advance.

Yii2 unique validator error display not set to form field

i am using yii2 RESTapi for my module .my problem the validation is working fne and the error msg also display in console as a json format but it's not set in form field .see the image for more info..please help me anyone ...
This is model
public function rules()
{
return [
[['username'], 'required'],
[['username'],'unique'],
}
view:
<?php $form = ActiveForm::begin([
'id' => 'cab-form',
'enableAjaxValidation' => true,
])
; ?>
<?= $form->field($model, 'username')->textInput(['maxlength' => true]) ?>
<div class="form-group">
<?= Html::submitButton( 'Create', ['class' => 'btn btn-success','id'=>'submit-btn']) ?>
</div>
<?php ActiveForm::end(); ?>
controller:
public function actionCreate(){
$model = new Cab;
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$post_data = Yii::$app->request->post();
$model->load($post_data);
$model->save();
return $model;
}
Thanks...
Unique require AjaxValidation to work. You need verify in your controller if an ajax request exist and return the validation encoded with JSON. See the example below:
if ($model->load(Yii::$app->request->post()) {
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
}

Laravel show errors if request form validation fails

I'm making a REST API that should validate data entry from the user, to achieve that, I made a Request class that has the rules function that it should do the validations.
Request class
class StoreUpdateQuestionRequest extends Request {
public function authorize() {
return true;
}
public function rules() {
$method = $this->method();
$rules = [
'question' => 'required|min:10|max:140',
'active' => 'boolean',
];
return $method !== 'GET' || $method !== 'DELETE' ? $rules : [];
}
}
So, in the controller, when I try to run an endpoint which it fires the validations, it does work, it fails when it's has to, but it doesn't show me the errors as I expect, even though I defined the error messages in the messages function contained in the Request class, instead of showing me that errors, it redirects me to a location. Which sometimes is the result of a request I made before or it runs the / route, weird.
Controller function
public function store(StoreUpdateQuestionRequest $request) {
$question = new Question;
$question->question = $request->question;
$question->active = $request->active;
if($question->save()) {
$result = [
'message' => 'A question has been added!',
'question' => $question,
];
return response()->json($result, 201);
}
}
Any ideas? Thanks in advance!
In order to make this work, you have to add an extra header to your request:
Accept: application/json
That did the trick.
You can use controller based validation as described in documentation https://laravel.com/docs/5.2/validation#manually-creating-validators
public function store(Request $request) {
$validator = Validator::make($request->all(), [
'question' => 'required|min:10|max:140',
'active' => 'boolean',
]);
if ($validator->fails()) {
return response()->json($validator->errors());
}
//other
}

Categories