yi_peppe
(Peppedantini)
January 17, 2019, 11:21am
1
Hello world, I’m migrating a Yii1 application to Yii2.
For a specific controller loading data is easily too long, so I want to do this:
the “view” action call the view that render just the skeleton of the page with a waiting message;
the view display page and register a js code that calls “viewajax” action;
the “viewajax” action load data then call the view to display them substituting the waiting message.
The following code worked with Yii1.
Controller
public function actionView($id) {
$sintesi = Sintesi::findOne($id);
if ($this->ajaxAttivo()) {
return $this->render('view', [
'corrente' => $sintesi,
'chiamaAjax' => true,
]);
}
$sintesi->elabora();
$dataProvider = new ArrayDataProvider([
'allModels' => $sintesi->risultato->tabella,
'pagination' => false,
]);
return $this->render('view', [
'corrente' => $sintesi,
'chiamaAjax' => false,
'searchModel' => new SintesiSearch(),
'dataProvider' => $dataProvider,
]);
}
public function actionViewajax($id) {
$sintesi = Sintesi::findOne($id);
$sintesi->elabora();
$dataProvider = new ArrayDataProvider([
'allModels' => $sintesi->risultato->tabella,
'pagination' => false,
]);
return $this->renderAjax('view', [
'corrente' => $sintesi,
'chiamaAjax' => false,
'searchModel' => new SintesiSearch(),
'dataProvider' => $dataProvider,
]);
}
View
if ($chiamaAjax) {
$ajax = GenLib::codiceAjaxView('tabdati', ['sintesi/viewajax', 'id' => $corrente->id);
$this->registerJs($ajax, \yii\web\View::POS_LOAD);
echo Html::beginTag('div', ['id' => 'tabdati']);
echo 'Caricamento dati... Attendere';
echo Html::endTag('div');
} else {
$colonne = $corrente->risultato->colonne;
echo DynaGrid::widget([
'options' => ['id' => 'lst-' . $searchModel->tableName()],
'theme' => 'panel-info',
'gridOptions' => [
'dataProvider' => $dataProvider,
'filterModel' => null,
'pjax' => false,
'panel' => [
'heading' => '<p class="panel-title">' . $corrente->indicatore->descrizione . '</p>',
],
'panelHeadingTemplate' => '{title}<div class="clearfix"></div>',
'toolbar' => false,
'hover' => true,
'floatHeader' => Yii::$app->user->isJsActive,
'responsiveWrap' => false,
],
'columns' => $colonne,
]);
}
GenLib
public static function codiceAjaxView($destinazione, $indirizzo) {
$codice = "
jQuery.ajax({
type: 'POST',
dataType: 'html',
url: '" . Url::to($indirizzo) . "',
success: function(data){
document.getElementById('" . $destinazione . "').innerHTML = data;
},
error: function(){
alert('Errore Ajax');
}
});
";
return $codice;
}
Step 1 and 2 correctly runs but the js code return “errore”. I’m not so able with js and Ajax; can someone help me? Thanks
machour
(Mehdi Achour)
January 17, 2019, 12:10pm
2
Hi,
Open your browser inspector, and see what’s the URL being called using ajax.
Does it seem correct ? What is it outputting ?
yi_peppe
(Peppedantini)
January 17, 2019, 12:26pm
3
The link is correct. This is the js code generated in the page:
<script>jQuery(window).on('load', function () {
jQuery.ajax({
type: 'POST',
dataType: 'html',
url: '/mia2/web/index.php/sintesi/viewajax?id=70',
success: function(data){
document.getElementById('tabdati').innerHTML = data;
},
error: function(){
alert('Errore Ajax');
}
});
});</script>
In the log I find a “400 - Bad Request” error.
machour
(Mehdi Achour)
January 17, 2019, 12:29pm
4
If it’s showing the “Errore Ajax” alert, then the URL called by Ajax is returning an Error code.
See it’s details in your browser developer tools.
Like this for example:
Here, the Status Code is “200”, and it’s okay.
What does it give for your URL?
yi_peppe
(Peppedantini)
January 17, 2019, 12:35pm
5
machour:
If it’s showing the “Errore Ajax” alert, then the URL called by Ajax is returning an Error code.
See it’s details in your browser developer tools.
Like this for example:
Here, the Status Code is “200”, and it’s okay.
What does it give for your URL?
In the log I find a “400 - Bad Request” error.
machour
(Mehdi Achour)
January 17, 2019, 12:41pm
6
We’re making progress. This error can sometimes mean that you’re using the wrong HTTP method.
Your ajax call is doing a POST. Did you configure your controller to accept POST for that action?
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => \yii\filters\VerbFilter::class,
'actions' => [
'viewajax' => ['post'],
],
],
];
}
yi_peppe
(Peppedantini)
January 17, 2019, 2:06pm
7
The verb filter was not configured in the behaviors. But the code you suggest doesn’t solve the problem. Same error 400.
Curiosly the specific message (sorry, I didn’t see it before) of the error is “Unable to verify your data submission.” But there is no data submission.
machour
(Mehdi Achour)
January 17, 2019, 4:21pm
8
1 Like
yi_peppe
(Peppedantini)
January 18, 2019, 7:45am
9
Great!
Setting “$enableCsrfValidation = false” it works.
Now the question is: why does Yii identity this as a CSRF request? I’m working on my local (and closed) dev system.
machour
(Mehdi Achour)
January 18, 2019, 9:28am
10
Yii identifies this request as a CSRF request, because you didn’t pass along the CSRF token when performing the Ajax request.
Disabling the feature is a really bad practice, and you shouldn’t do it, as once your website is in production, any malicious user will be able to perform POST requests to this URL.
Warning: Disabling CSRF will allow any site to send POST requests to your site. It is important to implement extra validation such as checking an IP address or a secret token in this case.
You may consider it harmless in this particular case, but it’s a good practice to always protect your endpoints by default.
You can pass it from your ajax request by modifying it like this:
<script>jQuery(window).on('load', function () {
jQuery.ajax({
type: 'POST',
dataType: 'html',
url: '/mia2/web/index.php/sintesi/viewajax?id=70',
+ data: {_csrf: : yii.getCsrfToken()}
success: function(data){
document.getElementById('tabdati').innerHTML = data;
},
error: function(){
alert('Errore Ajax');
}
});
});</script>
and undoing setting $enableCsrfValidation = false
which is a bad quick fix.
Check this SO entry for more details.
2 Likes
yi_peppe
(Peppedantini)
January 18, 2019, 10:24am
11
Thank you very much.
Now it runs perfectly. And sure.
1 Like