Yii2 - Change Language - php

I have a problem with my advanced template when I try to change page using internationalization.
I try to explain. To use the internationalization on my site I have follow this steps:
In params.php, I have added this:
<?php
return [
'adminEmail' => 'admin#example.com',
'languages' => [
'en' => 'English',
'it' => 'Italian',
],
];
I have added this in my frontend\views\layouts\main.php to call on my website the languages insert above:
<?php
foreach(Yii::$app->params['languages'] as $key => $language){
echo '<span class="language" id ="'.$key.'">'.$language.' | </span>';
}
?>
after I have created a new file named main.js. To permit to yii2 to see the main.js file I added this in the AppAsset.php (is it correct?). In this file I insert this:
$(function(){
$(document).on('click','.language', function(){
var lang = $(this).attr('id');
$.post('index.php?r=site/language', {'lang':lang},function(data){
location.reload();
});
});
$(document).on('click','.fc-day', function(){
var date = $(this).attr('data-date');
$get('index.php?r=event/create',{'date':date},function(data){
$('#modal').modal(show)
.find('#modalContent')
.html(data);
});
});
$('#modalButton').click(function(){
$('#modal').modal(show)
.find('#modalContent')
.load($(this).attr('value'));
});
});
after that in the sitecontroller.php I have added this:
public function actionLanguage()
{
if(isset($_POST['lang'])){
Yii::$app->language = $_POST['lang'];
$cookie = new Yii\web\cookie([
'name'=>'lang',
'value'=>$_POST['lang']
]);
Yii::$app->getResponse()->getCookies()->add($cookie);
}
}
after in config\main.php I have added this in components:
'components' => [
'i18n' => [
'translations' => [
'app' => [
'class' => 'yii\i18n\PhpMessageSource',
//'basepath' => #app/messages,
'sourceLanguage' => 'it',
'fileMap' => [
'app' => 'app.php',
'app/error' => 'error.php',
],
],
],
],
finally i have create on the root a folder called messages\it and messages\en and inside two files (one per folder) called app.php I have insert this text:
<?php
return [
'Benvenuto' => 'Welcome'
];
that's all...but after load my home page (correctly) when i click on one of the languages (Italian or English) I see the following messages:
jquery.js?ver=1.11.3:4 POST http://localhost/mdf/frontend/web/index.php?r=site/language 400 (Bad Request)
And If I try to paste directly this url, I obtain only a blank page:
http://localhost/mdf/frontend/web/index.php?r=site/language

This is only a partial response to your question
The blank page when you invoke using browser could be related to the fact that you don't render nothings in this case.
try manage the ajax this way
public function actionLanguage()
{
if (Yii::$app->request->isAjax) {
$data = Yii::$app->request->post();
if(isset($data['lang'])) {
Yii::$app->language = $data['lang'];
$cookie = new Yii\web\cookie([
'name'=>'lang',
'value'=>$_POST['lang']
]);
Yii::$app->getResponse()->getCookies()->add($cookie);
return;
}
} else {
return $this->render('index', []);
}
}

Related

Select2 Widget & Pjax Yii2

I'm trying to add multiple Select2 widgets dynamically in the TabularForm using Pjax (build-in Ajax component in Yii2). For some reason the Select2 input is rendering on the wrong place at the top of the view (see gif1 below). As I understood, this issue is related specifically to the Select2 widget as everthing is working fine if I use some default component e.g. Html::a (see gif2 below).
gif1: https://i.imgur.com/YMh5dNb.gif
gif2: https://i.imgur.com/sJkTDkO.gif
How I can get rid of that strange behaviour with the Select2 widget? Thanks is advance!
Controller:
class ProfileController extends Controller
{
// ...
public function actionCreate()
{
if (Yii::$app->request->isAjax) {
// some logic here ...
return $this->renderAjax('object/create', [
// ...
]);
}
}
// ...
}
View:
// ...
use kartik\select2\Select2;
use kartik\select2\Select2Asset;
Select2Asset::register($this);
// a bunch of html code
<?php Pjax::begin(['id' => 'product-add']); ?>
$form1 = ActiveForm::begin();
$attribs = [
'name' => [
'type' => TabularForm::INPUT_RAW,
'value' => function($productModel) {
return Select2::widget([
'name' => 'state_10',
'data' => ['1' => '1', '2' => '2'],
'pjaxContainerId' => 'product-add',
'options' => [
'placeholder' => $productModel->tmpId,
'multiple' => true
],
]);
//return Html::a('product ' . $productModel->tmpId); <- works fine if I use this piece of code
},
],
// ...
Html::a("Add", ['profile/create'], ['class' => 'btn btn-primary'])
// ...
<?php ActiveForm::end(); ?>
<?php Pjax::end(); ?>
// ...
After some closer examination I found the solution. For those who will also face the same issue, you need to initialize your widget (Select2 in my case) before the pjax response, e.g. in your Controller:
class ProfileController extends Controller
{
// ...
public function actionCreate()
{
if (Yii::$app->request->isAjax) {
// some logic here ...
// initialize the widget with an appropriate id
$this->view->registerJs("$({$product->tmpId}).select2();");
return $this->renderAjax('object/create', [
// ...
]);
}
}
// ...
}
And somewhere in your View:
Select2::widget([
'id' => $productModel->tmpId, // set your unique id here
'name' => $productModel->tmpId,
'data' => ['1' => '1', '2' => '2'],
// ...
]);

yii2, partially render view with new data

New to yii2 and PHP, ran into a break here.
Based on this and this post, I tried recreating the AJAX call.
Right now, using the Kartik SwitchInput widget, I'm at least trying to get the value into the controller and then return it to another place on the index page.
Here's what's in the view
...
<?= GridView::widget([
'dataProvider' => $customers,
'columns' => [
...
[
'label' => 'Status',
'format' => 'raw',
'attribute' => 'status',
'value' => function($models){
return SwitchInput::widget([
'name' => $models->id,
'value' => $models->status,
'pluginEvents' => [
'switchChange.bootstrapSwitch' => 'function(e) {
$.ajax({
method: "POST",
url: "'.Url::to(['update-status']).'",
data: { "status": e.currentTarget.checked, "id": e.currentTarget.name },
error:function(res){
console.log(res.responseText);
}
})
console.log(`${e.currentTarget.checked} ${e.currentTarget.name}`);
}'
]
...
Here's the controller:
class CustomerController extends Controller{
public function actionIndex(){
$customers = new ActiveDataProvider([
'query' => Customer::find()
]);
$models = $customers->getModels();
return $this->render('index', [
'customers' => $customers,
'models' => $models
]);
}
public function actionUpdateStatus(){
$status = Yii::$app->request->post('status');
$id = Yii::$app->request->post('id');
return $this->renderPartial('index', [
'status' => $status,
'id' => $id
]);
}
}
Whenever I flip the switch, it returns a 500 Internal error. Console.logging it revealed: $customers is undefined.
From what I realised, whenever I make an actionUpdateStatus call, Yii re-renders the view completely anyway, and tries to find the $customers, which isn't in the UpdateStatus.
How do I return the switch data, separately, back into the same view, then?
I posted one of the answers you mentioned, and i havent specified one thing there which is reloading of the gridview which wasnt the requirement there, but can be done using $.pjax.
A few things you need to look at
You dont need any view for the updateStatus action as per your requirement.
You just need to return some status code to the ajax call that you are using inside the gridView for the switch input, and refresh your gridview to load the new updated status.
In ajax success callback function check if that status code is ok then you should refresh the gridview rather than using render partial.
And you are not updating anything in the updateStatus? you need to switch the status
So change your action to the following
public function actionUpdateStatus()
{
try {
$status = Yii::$app->request->post('status');
$id = Yii::$app->request->post('id');
$model = Customer::findOne($id);
$model->status=$status;
if(!$model->save()){
throw new Exception(implode("\n",\yii\helpers\ArrayHelper::getColumn($model->errors,'0'));
}
return $this->asJson(['success' => true]);
} catch (Exception $e) {
return $this->asJson(['success' => false, 'message' => $e->getMessage()]);
}
}
Make sure you have wrapped the GridView inside Pjax start and end and add an id to the Pjax widget
<?php
Pjax::begin(['id'=>'pjax-container']);
echo GridView::widget([
'dataProvider' => $customers,
'columns' => [
.......
]);
Pjax::end();
?>
And your ajax call to the following
'switchChange.bootstrapSwitch' => 'function(e) {
$.ajax({
method: "POST",
url: "'.Url::to(['update-status']).'",
dataType:'json',
data: { "status": e.currentTarget.checked, "id": e.currentTarget.name },
success:function(data){
if(data.success){
$.pjax({container: "#pjax-container"});
}else{
console.log(data.message);
}
},
error:function(res){
console.log(res.responseText);
}
});
}'

How to use hyphen/dash in a url?

I have this button in the _form.php file.
'buttons' => [
'replace' => function($url, $model) {
return Html::a(
'Replace',
[
'/european-countries/replace',
'countryIdReplacement' => '123' // Problem here.
]
);
},
],
My controller:
public function actionReplace($countryIdReplacement) {
// My code.
}
The URL is:
http://my-site/european-countries/replace?countryIdReplacement=123
I want to use this variable format:
http://my-site/european-countries/replace?country-id-replacement=123
But PHP doesn't allow to use that format. This is not allowed:
actionReplace($country-id-replacement)

add button to perform an action prior to sending to view page

I'm working on a program that is a reservation service for lab systems using Yii2.0. I've been using Yii for a little while but for some reason this one is stumping me
I have all of the systems listed in a gridview and I'd like to have a button in the actionColumn that will run the 'reserve' action and then show the view for the individual system.
I have the button added and it brings the user to the view page but I don't know what I need to do to have it run the reserve action first...or if it's even possible. I've tried pointing it to the reserve action in the controller but of course that looks for a view page rather than an action.
Here's some of the code from what I've been trying after looking through many pages of suggestions:
On the index page
['class' => 'yii\grid\ActionColumn',
'template' => '{reserve}',
'buttons' => [
'reserve' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-ok-circle"></span>',
$url,
[
'title' => 'Reserve',
'data-method' => 'post',
'data-pjax' => 0,
]);
}
],
'urlCreator' => function ($action, $model, $key, $index) {
return Url::toRoute(['cml/view', 'id' => $key]);
}
Function in Controller
public function actionReserve($id)
{
$model = $this->findModel($id);
if ($model->fkReservedTo == 1)
{
$model->fkReservedTo = Yii::$app->user->id;
// shouldn't you call save here
$model->save();
return $this->redirect(['view','id'=>$id]);
}
else
{
Yii::$app->session->setFlash('error', 'This system is not available to be reserved');
return $this->showAlert();
}
}
Any suggestions would be appreciated.
Change
return Url::toRoute(['cml/view', 'id' => $key]);
to
return Url::toRoute(['cml/reserve', 'id' => $key]);
in your urlCreator function.

Yii2 - switch response between rest (json) and normal html output

I need a way to active rest when some one using ajax X-Requested-With
and deactivate that when doesn't. with this way I can handle search engine
or users without ajax.(improve SEO)
some research: (using behaviors)
public function behaviors()
{
return [
'verbs' => [
'class' => \yii\web\ResponseFilter::className(),
'actions' => [
'something' => [
'format' => Response::FORMAT_JSON,
],
],
],
];
}
check request headers and change response.
or: (edit rest controller)
edit $serializer = 'yii\rest\Serializer'; to $serializer = null;
or (override after action of rest controller)
public function afterAction($action, $result)
{
$result = parent::afterAction($action, $result);
return $this->serializeData($result);
}
and remove serializeData() some how...
but what is the ultimate way?
I think these ways are not fine...

Categories