How do we pass url method in the kartik v sidenav widget
echo SideNav::widget([
'type' => $type, 'encodeLabels' => false,
'heading' => $heading,
'items' => [
Yii::$app->user->isGuest ?
['label' => 'LOGIN', 'url' => '', 'active' => ($item == 'login')] :
['label' => 'LOGOUT', 'url' => 'site/logout', 'linkOptions' => ['data-method' => 'post']],
],
]);
I get error as logout needs method post
Where do we pass the data method in this widget
I also use kartk v sidenav widget andthis is my SiteController
class SiteController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'access' => [
.......
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
}
in sidenav i simply have this
['label' => 'logout', 'url'=>Url::to(['/site/logout'])],
I had the same problem and used the template option for the SideNav widget. I was inspired by this SO answer.
Your code would look like this:
echo SideNav::widget([
'type' => $type, 'encodeLabels' => false,
'heading' => $heading,
'items' => [
Yii::$app->user->isGuest ?
['label' => 'LOGIN', 'url' => '', 'active' => ($item == 'login')] :
['label' => 'LOGOUT', 'icon' => 'log-out', 'url'=>Url::to(['/site/logout']), 'template' => '{icon}{label}' ]
],
]);
I added an icon as a little extra example.
Related
I have a controller with an action method:
namespace frontend\controllers;
class EmployeeController extends FrontController
{
/**
* Deletes an existing Employee status.
* #param integer $id
* #return mixed
*/
public function actionDeleteStatus($status_id)
{
error_log("actionDeleteStatus " . $status_id);
return $this->redirect(['update']);
}
}
In update form, I have a detail GridView, in which I want to add a "delete" link with an URL for this method as a GET request.
I try to get the URL with this: Url::toRoute(['employee/deleteStatus','status_id' => $model->status_id]) which gives me an url like /employee/deleteStatus?status_id=4 and throws a 404, here is the detailed code:
<div class="col-xs-12">
<?php
echo Html::label(Yii::t('app', 'Employee status history'));
echo GridView::widget([
'summary' => '',
'options' => [
'id' => 'status-history',
],
'emptyText' => '',
'export' => false,
'dataProvider' => $statusHistory,
'columns' => [
[...],
[
'class' => 'kartik\grid\DataColumn',
'attribute' => 'status_id',
'headerOptions' => [ 'class' => 'kv-grid-hide' ],
'contentOptions' => [ 'class' => 'kv-grid-hide' ]
],
[
'class' => 'yii\grid\ActionColumn',
'urlCreator' => function($action, $model, $key, $index) {
return Url::toRoute(['employee/deleteStatus','status_id' => $model->status_id]);
},
'template' => '{delete}',
'contentOptions' => ['class' => 'column-action'],
'buttons' => [
'delete' => function ($url, $model, $key) {
if (Yii::$app->user->can('globalDAF')) {
$options = [
'title' => Yii::t('app', 'Delete'),
'aria-label' => Yii::t('app', 'Delete'),
'data-confirm' => Yii::t('app', 'Sure to delete status?'),
'data-method' => 'post',
'data-pjax' => '0',
'class' => 'btn-llyc'
];
return Html::a('<span class="glyphicon glyphicon-remove"></span>', $url, $options);
} else {
return;
}
}
]
]
],
'hover' => true,
'responsiveWrap' => false
]);
?>
</div>
Is the url generation wrong? Why am I getting a 404?
Thanks.
For example, index becomes actionIndex, and hello-world becomes
actionHelloWorld.
Note: The names of the action methods are case-sensitive. If you have
a method named ActionIndex, it will not be considered as an action
method, and as a result, the request for the index action will result
in an exception. Also note that action methods must be public. A
private or protected method does NOT define an inline action.
Link
Url::toRoute(['employee/delete-status','status_id' => $model->status_id])
Or in config file:
'urlManager' => [
'class' => 'yii\web\UrlManager',
#code ..
'rules' => [
'employee/deleteStatus' => 'employee/delete-status',
],
],
I have a form that allows a user to edit his information and upload an image. The image upload is optional but when I submit the form, I always have an error telling me that the image has not been uploaded.
Here is the partial fieldset code:
public function init() {
$this->add([
'name' => 'avatar',
'type' => 'file',
'attributes' => [
'id' => 'avatar',
'class' => 'input-file',
'accept' => 'image/*'
],
'options' => [
'label' => 'avatar',
]
]);
}
This fieldset implements InputFilterProviderInterface, so here is the code:
public function getInputFilterSpecification() {
return [
'avatar' => [
'type' => '\Zend\InputFilter\FileInput',
'allow_empty' => true,
'required' => false,
'validators' => [
[
'name' => 'FileExtension',
'options' => [
'extension' => ['jpg, jpeg, png'],
'message' => 'wrong_type_file'
]
],
[
'name' => 'FileSize',
'options' => [
'max' => '2MB',
'message' => 'file_too_large'
]
]
],
],
];
}
Despite the fact that this field is not required and allow_empty option is true, when I submit the form and debug the value, I still have validation that fails and this as my debug value:
'avatar' =>
array (size=5)
'name' => string '' (length=0)
'type' => string '' (length=0)
'tmp_name' => string '' (length=0)
'error' => int 4
'size' => int 0
Do you know how could I validate my form event when no file is downloaded?
Thanks in advance for your answers!
EDIT 1: Here are the messages returned by the form after submission:
'avatar' =>
array (size=2)
'fileExtensionNotFound' => string 'Extension d'image non admise (.jpg, .jpeg, .png seulement)'
'fileSizeNotFound' => string 'Le fichier est trop volumineux, 2097152 maximum.' (length=48)
EDIT 2: the action in the controller:
$prg = $this->fileprg($form);
if ($prg instanceof Response) {
return $prg;
} elseif (is_array($prg)) {
$data = $form->getData();
if ($form->isValid()) {
if ($data['person']['file']) {
// #TODO upload file
}
if (!$this->personMapper->updatePerson($data)) {
$this->flashMessenger()->addErrorMessage($this->translator()->translate('error_occurs_backup'));
} else {
$this->flashMessenger()->addSuccessMessage($this->translator()->translate('data_saved'));
}
} else {
// #TODO file error management
\var_dump('not valid');
\var_dump($form->getMessages());
}
}
I try to get POST Variables in my controller from view with:
<?= GridView::widget([
'dataProvider' => $dataProvider_products,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'label'=>'Name',
'format' => 'raw',
'value'=>function ($data) use ($model, $dataProvider_products) {
return Html::a($data['name'],['suppliers_orders/addproduct', 'order' => $model->id, 'product' => $data['id'],
'data-method'=> 'post',
'data-params' => ['dataProvider' => $dataProvider_products],
]);
},
],
'supplier_product_number',
'size',
'price_net',
],
]); ?>
The parameter dataProvider will always be sent with the URL and results in a GET variable. What is wrong, respectively what must be done, that dataProvider will be sent as POST variable?
Part of my controller is:
public function actionAddproduct($order, $product){
// look for GET variable
$request = Yii::$app->request->get('data');
$dataProvider = $request['params']['dataProvider'];
// look for POST variable
$param1 = Yii::$app->request->post('dataProvider', null);
$dataProvider_suppliers_orders_products = $dataProvider;
return $this->actionView($order);
}
First of all you are passing the data-params in the url parameter rather than setting in the options parameter, so yes it will always be sent as query string no matter you pull your hairs off and become bald ¯\_(ツ)_/¯.
Then According to the DOCS
If the attribute is a data attribute as listed in
yii\helpers\Html::$dataAttributes, such as data or ng, a list of
attributes will be rendered, one for each element in the value array.
For example, 'data' => ['id' => 1, 'name' => 'yii'] generates
data-id="1" data-name="yii" and 'data' => ['params' => ['id' => 1,
'name' => 'yii'], 'status' => 'ok'] generates
data-params='{"id":1,"name":"yii"}' data-status="ok"
So, you need to change the anchor to look like
Html::a($data['name'], ['suppliers_orders/addproduct', 'order' => $model->id, 'product' => $data['id']], [
'data' => [
'method' => 'POST',
'params' => ['dataProvider' => $dataProvider_products]
]
]);
But since you are passing the $dataProvider object to the params it aint going to work because it will be changed to [Object Object] but if it is simple text then it will work, otherwise you have to change your approach.
Your complete code for the GridView should look like below
<?=
GridView::widget([
'dataProvider' => $dataProvider_products,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'label' => 'Name',
'format' => 'raw',
'value' => function ($data) use ($model, $dataProvider_products) {
return Html::a($data['name'], ['suppliers_orders/addproduct', 'order' => $model->id, 'product' => $data['id']], [
'data' => [
'method' => 'POST',
'params' => ['dataProvider' => $dataProvider_products]
]
]);
},
],
'supplier_product_number',
'size',
'price_net',
],
]);
?>
I have route.php like below :
Route::get('/edit/{num}', [
'as' => 'department.edit',
'middleware' => ['admin'],
'uses' => 'DepartmentsController#edit'
]);
Route::post('/update/{num}', [
'as' => 'department.update',
'middleware' => ['admin'],
'uses' => 'DepartmentsController#update'
]);
And edit.blade.php as below :
{!! Form::model($department, array('route' => ['department.update', Crypt::encrypt($department->id)], 'id' => 'department_update', 'class' => 'form-horizontal row-border')) !!}
#include('admin.departments._form')
{!! Form::label('', '', array('class' => 'col-md-2 control-label')) !!}
{!! Form:: submit('Update', ['class' => 'btn btn-success']) !!}
{!!form::close()!!}
And the DepartmentsController.php update() as :
public function update($id, Request $request) {
$id = Crypt::decrypt($id);
dd($_POST);
}
The above showing the POST variables :
array:3 [▼
"_token" => "UI6tBMuJlwmGZuaeB9ilJq6v0wUMOgKRlEY4eY0I"
"name" => "Material Management"
"department_code" => "MMD"
]
But if I try to output dd($request), it throws error
ReflectionException in AbstractCloner.php line 245: Class 1 does not
exist
Whats wrong ? Where I have made the mistake
Try this way, move your $request to 1st params.
public function update(Request $request, $id) {
$id = Crypt::decrypt($id);
dd($request->all());
dd($_POST);
}
I have a route that has a parameter and its tripping my firewall thinking it needs to be logged in first. I tried to setup the pattern to use the name form at as used in the route but it still saying it requires authentication.
is there a special way to get the patter to work with parameters? I'm failing to see how to so that.
Thanks
$app->register(new Silex\Provider\SecurityServiceProvider(), [
'security.firewalls' => [
'login' => [
'pattern' => '^/login$',
'anonymous' => true
],
'pwdRecovery' => [
'pattern' => '^/recover',
'anonymous' => true
],
'newPassword' => [
'pattern' => '^/newpassword$',
'anonymous' => true
],
// Any other URL requires auth.
'authenticated' => [
'pattern' => '^.*$',
'form' => [
'login_path' => '/login',
'check_path' => '/authenticate'
],
'anonymous' => false,
'logout' => ['logout_path' => '/logout'],
'users' => $app->share(function() use ($app) {
return new App\Providers\UserServiceProvider();
}),
]
],
'security.access_rules' => [
['^/admin', 'ROLE_ADMIN']
],
'security.encoder.digest' => $app->share(function() {
return new BCryptPasswordEncoder(15);
})
]);
This may be a regex problem. I can pass parameters to the ^/recover route just fine.
$app->get('/recover/{id}', function (Request $request, $id) use ($app) {
error_log(print_r((int) $id,1).' '.__FILE__.' '.__LINE__,0);
});
But if I add $ to that route like ^/recover$ then it redirects to login because the dollar sign dictates end of string.