Add class to a submenu container in Yii2 Bootstrap4 Nav widget - yii2

I'm using the Nav widget in Yii2. I have a dropdown menu as part of the nav menu but the dropdown is very long and extends beyond the bottom of the page and doesn't scroll. To solve this I am trying to add the pre-scrollable class to the submenu container. Try as I might I can't seem to make it work.
In the Yii manual for the Nav widget (https://www.yiiframework.com/extension/yiisoft/yii2-bootstrap/doc/api/2.0/yii-bootstrap-nav) under the $Items public property it says:
dropDownOptions: array, optional, the HTML options that will passed to
the yii\bootstrap\Dropdown widget.
I've also looked at the man page for the Dropdown widget (https://www.yiiframework.com/extension/yiisoft/yii2-bootstrap/doc/api/2.0/yii-bootstrap-dropdown).
The code I have for my Nav widget is like:
echo Nav::widget([
'options' => ['class' => 'navbar-nav ml-auto'],
'items' => [
['label' => 'Home', 'url' => ['/site/index']],
['label' => 'About', 'url' => ['/site/about']],
[
'label' => 'Dropdown menu',
//'dropDownOptions' => ['options' => ['class' => 'pre-scrollable']],
//'dropDownOptions' => ['class' => 'pre-scrollable'],
//'dropDownOptions' => ['submenuOptions' => ['class' => 'pre-scrollable']],
//'submenuOptions' => ['class' => 'pre-scrollable'],
//'submenuOptions' => ['options' => ['class' => 'pre-scrollable']],
//'submenuOptions' => ['dropDownOptions' => ['class' => 'pre-scrollable']],
//'dropDownOptions' => ['dropDownOptions' => ['class' => 'pre-scrollable']],
//'submenuOptions' => ['submenuOptions' => ['class' => 'pre-scrollable']],
//'options' => ['submenuOptions' => ['class' => 'pre-scrollable']],
//'options' => ['class' => 'pre-scrollable'],
//'options' => ['dropDownOptions' => ['class' => 'pre-scrollable']],
'items' => [
['label' => 'Dropdown menu item 1', 'url' => '#'],
['label' => 'Dropdown menu item 2', 'url' => '#'],
...
],
],
['label' => 'Contact', 'url' => ['/site/contact']],
],
]);
The commented out lines are some of the different ways I've tried to 'pass the HTML options to the yii\bootstrap\Dropdown widget' (in order of increasing desperation).
Please can someone put me right?
Thanks in anticipation!

The option dropDownOptions is tested successfully on Yii version 2.0.11.2 and Bootstrap v3.3.7:
'dropDownOptions' => ['class' => 'pre-scrollable'],
The result is additional class of tag contained submenu items
<ul id="w4" class="pre-scrollable dropdown-menu">
If you are using yii2-bootstrap4 - that options apparently renamed to dropdownOptions.
See Nav::renderDropdown() in the sources:
/**
* Renders the given items as a dropdown.
* This method is called to create sub-menus.
* #param array $items the given items. Please refer to [[Dropdown::items]] for the array structure.
* #param array $parentItem the parent item information. Please refer to [[items]] for the structure of this array.
* #return string the rendering result.
* #throws \Exception
*/
protected function renderDropdown($items, $parentItem)
{
/** #var Widget $dropdownClass */
$dropdownClass = $this->dropdownClass;
return $dropdownClass::widget([
'options' => ArrayHelper::getValue($parentItem, 'dropdownOptions', []),
'items' => $items,
'encodeLabels' => $this->encodeLabels,
'clientOptions' => false,
'view' => $this->getView(),
]);
}
https://github.com/yiisoft/yii2-bootstrap4/blob/219d19fba47b5499f01764789c3cd3ce7306e0f9/src/Nav.php#L207

Related

Is there a way to dynamically change maximumSelectionLength on kartik/select2 in yii2?

I am trying to update through javascript the maximumSelectionLength parameter of a select2 field (listeProduits) based on the value of a second select2 (nom_id) when it is changed.
I'm first storing the maxChildren values in a js table before loading the form so that I can access it on the client side when a new nom_id is selected.
The below approach doesn't work though as it messes up the listeProduits select2.
<script>
var nomMaxChildren = <?= json_encode(ArrayHelper::map(Nom::find()->asArray()->where(['type' => 'Boite'])->all(), 'id', 'max_children')); ?>;
alert(nomMaxChildren[1]);
</script>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'nom_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Nom::find()->asArray()->where(['type' => 'Boite'])->all(), 'id', 'nom'),
'options' => ['placeholder' => Yii::t('app','Select a name...')],
'pluginEvents' => [
"select2:select" => "function() {
$('select[name =\"listeProduits[]\"]').select2({
maximumSelectionLength: nomMaxChildren[\$(this).val()]
});
}",
]
]);?>
<label class="control-label"><?= Yii::t('app', 'Produits')?></label>';
<?= Select2::widget([
'attribute' => 'listeProduits',
'name' => 'listeProduits',
'data' => ArrayHelper::map(Produit::find()->asArray()->where(['statut_id' => 2])->andWhere(['boite_id' => null])->orWhere(['boite_id' => $model->id])->all(), 'id', 'numero_de_serie'),
'value' => (is_null($model->id)) ? null : ArrayHelper::map(Produit::find()->asArray()->where(['boite_id' => $model->id])->all(), 'id', 'id'),
'options' => ['placeholder' => Yii::t('app','Select products')],
'pluginOptions' => [
'allowClear' => true,
'multiple' => true,
'maximumSelectionLength' => (isset($model->nom)) ? $model->nom->max_children : null,
],
'showToggleAll' => false,
]);?>
Also if you have any idea on how to validate the fact that the maximumSelectionLength is ok on client side, it would be great :D
set maximumSelectionLength property dynamically :
$('#demo-select').select2({ maximumSelectionLength: 1 });

Call to undefined method app\models\User::instance() setting up kartik export yii2

Trying to set up kratik grid export in Yii after doing everything I keep getting
Call to undefined method app\models\User::instance()
here is my code
$exportedValues = [['class' => 'kartik\\grid\\SerialColumn'], ['attribute' => 'deduction_date'], ['attribute' => 'deduction_amount'], ['attribute' => 'deduction_remark'], ['class' => 'kartik\\grid\\ActionColumn']];
$export = ExportMenu::widget(['dataProvider' => $dataProvider, 'columns' => $exportedValues, 'noExportColumns' => [0, 3], 'columnSelectorOptions' => ['label' => 'Columns', 'class' => 'btn btn-danger'], 'target' => '_blank', 'fontAwesome' => true, 'dropdownOptions' => ['label' => 'Export', 'class' => 'btn btn-success']]);
echo GridView::widget(['dataProvider' => $dataProvider, 'filterModel' => $searchModel,
'columns' => [['class' => 'yii\\grid\\SerialColumn'],
'first_name', 'last_name', 'email_id', 'phone', ['class' => 'yii\\grid\\ActionColumn']]]); ?>
Try to install kartik, or check your kartik version
php composer.phar require kartik-v/yii2-widgets "*"
Had the same issue.
on the source code of ExportMenu.php I replaced:
$model = $modelClass::instance();
by:
$model = new $modelClass;
solved it for me.

Yii2 multiple ListView in one page

I'm using 2 widgets in one page, Both are using listview, one is for blogs and another one is for pages and both are using ScrollPager. I want to show more button in each separately. The problem is the show more button is shown only for pages but not for blog, if I remove the page widget it will display for blogs. I'm trying to display show more for pages and show more for blogs. I tried by pageParam but the problem still exist.
widget:
class UserPagesWidget extends \yii\base\Widget
{
public $usr_id;
public function run()
{
$dataProviderContent = new ActiveDataProvider([
'query' => Post::find()->Where(['user_id' => $this->usr_id])
->orderBy(['post_crdate' => SORT_DESC]),
'pagination' => [
'pageParam' => 'contentPagination',
'pageSize' => 5,
],
]);
return $this->render('/user/widget/pstList', [
'dataProviderContent' => $dataProviderContent,
]);
}
}
Render file:
<?= ListView::widget([
'dataProvider' => $dataProviderContent,
'summary'=>'',
'itemOptions' => ['class' => 'item'], // LY - FOR ( LOAD MORE )
'emptyText' => 'No Content',
'itemView' => function ($model, $key, $index, $widget) {
return $this->render('/user/profileContent/usr-pst-content',['model' => $model]);
},
'pager' => ['class' => \kop\y2sp\ScrollPager::className()],
]);
?>
Blog Widget:
class UserBlogsWidget extends \yii\base\Widget
{
public $usr_id;
public function run()
{
$dataProviderBlog = new ActiveDataProvider([
'query' => Blog::find()->Where(['user_id' => $this->usr_id])
->orderBy(['blog_update' => SORT_DESC]),
'pagination' => [
'pageParam' => 'blogPagination',
'pageSize' => 6,
],
]);
return $this->render('/user/widget/blgList', [
'dataProviderBlog' => $dataProviderBlog,
]);
}
}
Blog render file:
<?= ListView::widget([
'dataProvider' => $dataProviderBlog,
'summary'=>'',
'itemOptions' => ['class' => 'item'], // LY - FOR ( LOAD MORE )
'emptyText' => 'No Blogs',
'itemView' => function ($model, $key, $index, $widget) {
return $this->render('/user/profileContent/usr-blg-content',['model' => $model]);
},
'pager' => ['class' => \kop\y2sp\ScrollPager::className()],
]);
?>
Both widgets are called in one view file.
<div class="row chn-row">
<div class="col-sm-12" style="padding:15px">
<!-- separing -->
<?= UserPagesWidget::widget(['usr_id' => $model->user_id]) ?>
<!-- separing -->
</div>
<div class="col-sm-12" style="padding:15px">
<?= UserBlogsWidget::widget(['usr_id' => $model->user_id]) ?>
</div>
</div>
The problem is the show more button is displayed only for pages.
You need to adjust selectors to distinguish between two widgets. By default ScrollPager uses some generic selector (.list-view) that will match all list views. You should explicitly set ID for ListView widgets and use it in ScrollPager config as selector for widget initialization.
<?= ListView::widget([
// ...
'dataProvider' => $dataProviderBlog,
'options' => ['id' => 'blog-list-view'],
'pager' => [
'class' => \kop\y2sp\ScrollPager::className(),
'container' => '#blog-list-view',
'paginationSelector' => '#blog-list-view .pagination',
],
]) ?>
<?= ListView::widget([
// ...
'dataProvider' => $dataProviderContent,
'options' => ['id' => 'content-list-view'],
'pager' => [
'class' => \kop\y2sp\ScrollPager::className(),
'container' => '#content-list-view',
'paginationSelector' => '#content-list-view .pagination',
],
]) ?>
See https://kop.github.io/yii2-scroll-pager/#general-options

Yii2 Kartik SideNav How to set 'active' option

I have Kartik's SideNav (http://demos.krajee.com/sidenav-demo/profile/default) working properly by setting the url's to controller/action, but don't understand how to set the active option so that the menu stays open and the correct menu item stays selected.
I've tried setting 'active'=> 'controller/action' (see below) as well as
'active' => 'controller/action/default#demo' but to no avail. When I do set it as 'employee/employee-dashboard/default#demo' it does keep that one tab highlighted but won't change the others when I do it the same way on those tabs. The original was set to 'active'=> 'home' which I assume is just the action but that didn't work for me either.
$type = SideNav::TYPE_DEFAULT;
$heading = '<i class="glyphicon glyphicon-cog"></i> Employee Menu';
$item = '/employee/employee-dashboard/default#demo';
echo SideNav::widget([
'type' => $type,
'encodeLabels' => false,
'heading' => $heading,
'items' => [
// Important: you need to specify url as 'controller/action',
// not just as 'controller' even if default action is used.
//
// NOTE: The variable `$item` is specific to this demo page that determines
// which menu item will be activated. You need to accordingly define and pass
// such variables to your view object to handle such logic in your application
// (to determine the active status).
//
['label' => 'Dashboard', 'icon' => 'home', 'url' => Url::to(['/employee/employee-dashboard', 'type'=>$type]), 'active' => ($item == '/employee/employee-dashboard/default#demo')]
['label' => 'Paycheck Info', 'icon' => 'book', 'items' => [
['label' => '<span class="pull-right badge">10</span> W2 Forms', 'url' => Url::to(['/employee/w2-form', 'type'=>$type]), 'active' => ($item == 'w2-form')],
'active'=>($item == 'about')
where
$item = Yii::$app->controller->action->id;
This is how i used
<?php
$item = Yii::$app->controller->action->id;
echo SideNav::widget([
'type' => SideNav::TYPE_DEFAULT,
'heading' => 'Options',
'items' => [
[
'url' => Yii::$app->homeUrl,
'label' => 'Home',
'icon' => 'home',
'active'=>($item == 'index')
],
[
'label' => 'Help',
'icon' => 'question-sign',
'items' => [
['label' => 'About', 'icon'=>'info-sign', 'url'=>Yii::$app->homeUrl.'site/about', 'active'=>($item == 'about')],
['label' => 'Contact', 'icon'=>'phone', 'url'=>Yii::$app->homeUrl.'site/contact', 'active'=>($item == 'contact')],
],
],
],
]);
?>
One solution I found if you want to set the active menu item on a per page basis is:
Create a separate view file (e.g. sidemenu.php) with just the SideNav widget, which accepts a parameter called 'currentPage'.
echo SideNav::widget([
'type' => SideNav::TYPE_DEFAULT,
'heading' => 'Options',
'items' => [
[
'url' => Url::toRoute('/site/index'),
'label' => 'Home',
'icon' => 'file',
'active'=>($currentPage == 'home'),
],
[
'url' => Url::toRoute('/site/about'),
'label' => 'About',
'icon' => 'file',
'active'=>($currentPage == 'about'),
],
Then in the view page where you are rendering the menu, set the currentPage property -- for example:
echo $this->render('sidemenu', ['currentPage'=>'home']);
or
echo $this->render('sidemenu', ['currentPage'=>'about']);

Button in gridview yii2

I've create button view profile at gridview. When user click the button view profile, it will go to profile based on user_id. Here is the code.
<?= GridView::widget([
'dataProvider' => $dataProvider,
'id' => 'mygrid',
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'user_id',
'project_name',
['class' => 'yii\grid\ActionColumn'],
[
'label' => 'View Profile',
'format' => 'raw',
'content' => function($model) {
return Html::a('View', ['projectstudent/viewprofile', 'id' => $model->user_id],
['class' => 'btn btn-primary']);
}
],
]
]); ?>
At controller
public function actionViewprofile($id)
{
return $this->render('profile', [
'model' => $this->findModel($id),
]);
}
The requested page is not found. How can i fix the code? Thanks.
Here may be problem of controller name that u are specified, there is no need to define controller name if you want to call the action of same controller.
So replace so your code with this and try again
return Html::a('View', ['viewprofile', 'id' =>$model->user_id],
['class' => 'btn btn-primary']);