PJAX for this fragment code equivalent

Hi All,

My adoption to yii2 is very slow. It seems like learning new framework. Please help me on this.

I utilized many ajax form submission in my projects since they are faster then reloading everything ( I might be wrong here! But, using ajax is more convenient to me.). Below is my code in yii 1




     public function actionNextCode() {

        $stat = 'error';

        $message = 'Error in form submission not as Ajax!';

        $title = 'Generate new code';

        $nextCode = 'XXX';


        if (Yii::app()->request->isAjaxRequest && isset($_POST['Partner'])) {

            $model = new Partner;

            $model->attributes = $_POST['Partner'];


            if ($model->code == null || $model->code == '') {

                $model->code = 'XX';

            }


            $criteria = new CDbCriteria;

            $criteria->condition = 'code LIKE :code';

            $criteria->params = array(':code' => $model->code . '%');

            $criteria->order = 'code DESC';


            $latestModel = Partner::model()->find($criteria);


            if ($latestModel !== null) {

                $number = $latestModel->code;

                preg_match("#([a-z]+)([\d]+)#i", $number, $matches);

                $latestNum = $matches[2];

                $newNum = ((int) $latestNum) + 1;

                $model->code = $matches[1] . str_pad($newNum, strlen($latestNum), '0', STR_PAD_LEFT);

            } else {

                $model->code .= '01';

            }


            $stat = 'success';

            $message = 'New code is generated successfully.';

            $title = 'Generate new code';

            $nextCode = $model->code;

        }


        echo CJSON::encode(array(

            'status' => $stat,

            'message' => $message,

            'title' => $title,

            'nextCode' => $nextCode,


        ));


        Yii::app()->end();

    }




This is usually used to generate new value. It is called by pressing a button in a form. The process is using ajax. Now, when turn to yii2, I completely have no clue. Can anyone help guide me on turning this into pjax? FYI, I use message and title to display message using toastr. In yii2, I prefer to use krajee/growl.

Thank you in advance.

if you really need pjax, look at pjax tutorial

@Pasman,

Thank you for the prompt response and guidance. In my understanding now, pjax is just a kind of wrapper for the $.ajax call. However, I am still not successful in translating old ajax call in yii2.

Below is the code for the form

_add.php called by render method inside the index.php




<?php


use yii\helpers\Html;

use yii\widgets\ActiveForm;

use backend\models\Config;


/* @var $this yii\web\View */

/* @var $model common\models\ProductSearch */

/* @var $form yii\widgets\ActiveForm */

?>


<div class="product-form">

    <?php

    $form = ActiveForm::begin([

                'method' => 'post',

                'enableAjaxValidation' => false,

                'options' => ['id' => 'add-product-form'],

    ]);

    ?>


    <legend>Add product</legend>

    <div class="row">

        <div class="col-md-2"><?= $form->field($model, 'code') ?></div>

        <div class="col-md-7"><?= $form->field($model, 'name') ?></div>

        <div class="col-md-3"><?= $form->field($model, 'unit') ?></div>

    </div>

    <div class="row">

        <div class="col-md-2"> <?= $form->field($model, 'basePrice') ?></div>

        <div class="col-md-7"><?= $form->field($model, 'description') ?></div>

        <div class="col-md-3"><?= $form->field($model, 'status')->dropDownList(Config::getProductStatusOptions(), ['prompt' => 'Select status...']) ?></div>

    </div>


    <div class="form-group">

        <?= Html::submitButton('Add', ['class' => 'btn btn-primary btn-sm', 'onclick' => 'submitProduct(); return false;']) ?>

        <?= Html::resetButton('Reset', ['class' => 'btn btn-default btn-sm']) ?>

    </div>


    <?php ActiveForm::end(); ?>

</div>



and the js in index.php




<script type="text/javascript">

    function submitProduct() {

        $.ajax({

            type: 'POST',

            url: "<?= Yii::$app->getUrlManager()->createUrl('/product/addProduct') ?>",

            data: $('#add-product-form').serialize(),

            success: formProductSaved,

            dataType: 'json'

        });

    }


    function formProductSaved(data) {

    

        alert('heeelo');

        if (data.status == "success") {

            // ...

//            toastr.success(data.message, data.title);

            alert("success");

        } else { 

             // ....

//            toastr.error(data.message, data.title);

        }




    }

</script>



The problems:

  1. This suppose an ajax form submission, but somehow in firebug it is appear in All and XHR tabs. (suppose to be only in XHR).

  2. Error 404 File not found. I have the actionAddProduct() method in Product Controller.




public function actionAddProduct() {

        if (Yii::$app->request->isPost) {

            $model = new Product;


            if ($model->load(Yii::$app->request->post()) && $model->save()) {

                echo Json::encode(array(

                    'status' => 'success',

                    'title' => 'Add produdct',

                    'message' => 'Product is added successfully.',

                ));

            } else {

                $errors = array_map(function($v) {

                    return join(', ', $v);

                }, $model->getErrors());

                echo Json::encode(array('status' => 'error', 'title' => 'Add product', 'message' => "Errors: " . implode(" ", $errors)));

            }

        } else {

            throw new HttpException(400, 'Invalid request');

        }

    }



Can anyone help me with this?

TIA

Daniel

try using




<?= Yii::$app->getUrlManager()->createUrl('/product/add-product') ?>


or


<?= \yii\helpers\Url::to(['/product/add-product']); ?>



camelCased actions are accessed by - where the camel happens because camel cased controller actions are set in the base/controller createAction() to do so

i.e.

controller/someControllerAction

would be controller/some-controller-action.

if everything else is correct that should fix your 404 problem

also you don’t need a separate function for success.




<script type="text/javascript">

    function submitProduct() {

        $.ajax({

            type: 'POST',

            url: "<?= Yii::$app->getUrlManager()->createUrl('/product/add-product') ?>",

            data: $('#add-product-form').serialize(),

            success: formProductSaved,

            dataType: 'json',

            success: function(data) {

   			if (data.status == "success") {

 				alert("success");

                } else { 

   				alert(data.status);

                }

            }

        });

    }

</script>



a more universal/resuable approach would be something like.

first remove the onclick on the submit button




 $('#add-product-form').on('beforeSubmit', function(event) {

    	event.preventDefault();

    	var form =$(this);

        	$.ajax({

            	url: form.attr('action'),

            	type: form.attr('method'),

            	data:form.serialize(),

            	dataType: 'json',

            	error: function(xhr, status, error) {

                	alert('Error: '+error+' Status: '+status);

            	},

            	success: function(data) {

                	alert(data);

            	}

        	});

    	return false;

	});



if your form is a multipart i.e. accepts files then you could use something like




 $('#add-product-form').on('beforeSubmit', function(event) {

    	event.preventDefault();

    	var form =$(this);

        	$.ajax({

            	url: form.attr('action'),

            	type: form.attr('method'),

            	dataType: 'json',

            	data: new FormData($(this)[0]),

            	mimeType: 'multipart/form-data',

 				contentType: false,

            	cache: false,

            	processData: false,            	

            	error: function(xhr, status, error) {

                	alert(error+status);

            	},

            	success: function(data) {

                	alert(data);

            	}

        	});

    	return false;

	});



You can also just put the form id inline. As well as remove method post (defaults to post) and enableAjaxValidtion (defaults to false)




<?php $form = ActiveForm::begin(['id' => 'add-product-form']);?>



And the last thing I’m going to comment on is you are checking twice the if the method is post in your controller action

Thank you for your prompt and helpful response.

Regarding:

The first IF is to check whether the action is POST and should also check for the action is AJAX. I only use addProduct function if it is post and ajax. This is why I have else to throw exception.

The second IF is to get the attributes from the post.

Do you think only one IF is enough?

Thank you again.