html to pdf converter in yii2 with pagination in table - yii2

view:
<p>
<?= Html::a('Download This page', ['report'], ['class' => 'btn btn-danger']) ?>
</p>
controller:
public function actionReport()
{
// setup kartik\mpdf\Pdf component
$pdf = new Pdf([
'content' => $content,
'options' => ['title' => 'Krajee Report Title'],
'methods' => [
'SetHeader' => ['Krajee Report Header'],
'SetFooter' => ['{PAGENO}'],
]
]);
return $pdf->render();
}
This function works perfectly but my html table has pagination . so i am confused how to deal with table that has pagination.

You should disable the pagination. it all depends on how you define your data provider (read more about data providers here http://www.yiiframework.com/doc-2.0/guide-output-data-providers.html). Probably you should do something like this
************* = new ActiveDataProvider([
'pagination' => false,
..............
]);
I think you can also call it like
$dataProvider->pagination =false;
Just in case you need to disable it in a specific case.

Related

Yii2: Easy way to render page size selector at the paginator

Is there any easy and native way to add html rendering of items per page selector to the paginator at the ListView ? I've looked through the docs:
Yii widget listview
Yii data pagination
Yii widgets linkpager
Found everything I need, except rendering the page size selector. This is a bit strange, as this is a very common feature.
No there were no native way to do this, you can create your own or use this one:
Define in your model filter:
class YOUR_CLASS_FILTER extend YOUR_MODEL
...
public $pagesize; // Property pagesize.
const ITEMS_PER_PAGE_INIT = 12; // Initial items per page
...
//Add or edit this in the same model `search` method:
public function search($params){
...
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
// this $params['pagesize'] is an id of dropdown list that we set in view file
'pagesize' => ($this->pagesize) ? $this->pagesize : self::ITEMS_PER_PAGE_INIT,
],
]);
...
}
...
public function rules()
{
return [
...
[['pagesize'], 'integer'],
...
];
}
...
/**
* Return Static Array of elements per page
* #return array
*/
public static function itemsPerPage()
{
return array(
12 => 12,
24 => 24,
48 => 48
);
}
}
This is how i implemented in view file:
<?= $form->field($filter, 'pagesize')->dropDownList(
$filter->itemsPerPage(),
array(
'id' => 'pagesize',
'class' => 'form-control',
'onchange' => 'this.form.submit()',
))->label("Items per page: ")
?>
Create a menu with links to current page with the different per-page options as GET parameter:
<ul>
<li><?= yii\helpers\Html::a('10', yii\helpers\Url::current(['per-page' => 10])) ?></li>
<li><?= yii\helpers\Html::a('25', yii\helpers\Url::current(['per-page' => 25])) ?></li>
<li><?= yii\helpers\Html::a('50', yii\helpers\Url::current(['per-page' => 50])) ?></li>
</ul>

Yii2: How to use map() to show two fields in a Select2?

I am using a Select2 widget for Yii2. It shows a list with the ids of the users.
I need to show two fields defined in my model called Users: first_name_user and last_name_user. Like this:
Daniel Gates
John Connor
John Doe
Maria Key
But I don't know how use map() to show more than one field.
<?= $form
->field($model, 'id_user')
->widget(\common\widgets\Select2::classname(), [
'items' => \yii\helpers\ArrayHelper::map(\app\models\Users::find()->orderBy('name_user')->all(), 'id_user', 'name_user')
])
?>
Model
Add use app\models\Users; and use yii\helpers\ArrayHelper; at top.
public function userList()
{
$userList = [];
$users = Users::find()->orderBy('first_name_user')->all();
$userList = ArrayHelper::map($users, 'id_user', function ($user) {
return $user->first_name_user.' '.$user->last_name_user;
});
return $userList;
}
_form
<?= $form->field($model, 'id_user')->widget(Select2::className(), [
'data' => $model->userList(),
'options' => ['placeholder' => 'Select User'],
]) ?>
You need to use data option instead of items for Select2.
You need to modify your query to show the concatenated first_name_user and last_name_user as an alias and then return it along with the id column to be used in Select2 by ArrayHelper::map().
It's better to add a function to the model you are using to populate the form and return the results from there to the ArrayHelper::map().
Your query should look like
function userList(){
return \app\models\Users::find()
->select([new \yii\db\Expression('[[id_user]],CONCAT([[first_name_user]]," ",[[last_name_user]]) as full_user_name')])
->orderBy('name_user')
->all();
}
Your form field should look like below
<?=
$form->field($model, 'id_user')->widget(Select2::className(), [
'data' => \yii\helpers\ArrayHelper::map($model->userList(), 'id_user', 'full_user_name'),
'options' => [
'placeholder' => 'Select User',
'id' => 'id_user'
],
'theme' => Select2::THEME_DEFAULT,
'pluginOptions' => [
'allowClear' => true
],
]);
?>

How do I add Kartik ActiveField on Kartik DetailView?

I'm using Kartik's awesome extension called DetailView. I'd like to add the Kartik widget called ActiveField to the DetailView. What is the proper way to use the ActiveField widget in the DetailView widget?
The code I'm using generates the error First parameter must either be an object or the name of an existing class. According to Kartik's documentation, any widget (not just the DetailView widgets) can be used. What is the proper way to do that?
$attributes = [
['attribute' => 'definition_summary',
'format' => 'raw',
'type'=>DetailView::INPUT_WIDGET,
'widgetOptions'=>[
'class'=>ActiveField::className(),
'addon' => ['prepend' => ['content' => '#']],
],
];
echo DetailView::widget([
'model' => $model,
'attributes' => $attributes,
]);

Displaying subdirectory name in the url in Yii2 for static pages

Iam creating static pages for a client using Yii2. I am using yii2 because the client has some other requirements to scale up the web later. I use Yii2 Basic app. The yii2 basic has default pages like about, contact etc.
The url for those pages after enabling pretty url is
www.example.com/about
etc
Now i need to create pages
"xyz.php"
under a sub directory like
"abc"
. So i need my url to be www.example.com/abc/xyz
How do i achieve this? to be informed iam a learner, I followed url rules, helpers but did not find a strong solution.
create a controller like StaticController.php and use the yii\web\ViewAction
http://www.yiiframework.com/doc-2.0/yii-web-viewaction.html
As an example:
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\filters\AccessControl;
/**
* StaticController is only for displaying static pages.
*/
class StaticController extends Controller
{
public $defaultAction = 'page';
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['page'],
'allow' => true,
'roles' => ['#'],
],
],
],
];
}
public function actions()
{
return [
'page'=>array(
'class'=>'yii\web\ViewAction',
'viewPrefix'=>null, // or set a specific directory e.g. 'static-pages' if you want to store the static pages in a subdirectory
),
];
}
}
And add this Rule to your UrlManager (where static is your controller name)
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<controller:static>/<view:.*>' => '<controller>',
...
]
]
Now you can store your static pages in the directory /view/static/
e.g. index.php, test.php or even in subdirectories /sub/test2.php
The urls would be like /static (or /static/index), /static/test1, /static/sub/test2
The 1st pathname is of course the controller name, but you can also change the url rule to something else or rename the controller.
config/web.php
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'abc/<view:\S+>' => 'site/page',
]
]
I had a situation where I wanted the URL to indicate a sub page (like 'website/page/sub-page) but I didn't think it made sense to have a separate controller. (At the moment I just have one controller; SiteController.php.)
I am recreating the site structure of an existing site in a new Yii2 Basic site.
Client has a page called 'laptop-repair' in their existing site with a number of pages linked from it, e.g. 'laptop-overheating'. So the URI needed to look like 'laptop-repair/laptop-overheating'.
The solution:
In urlManager in config>web.php I add a new rule (Nb. the order of rules is important, the earlier rules are prioritised):
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'/' => 'site/index',
[
'pattern' => 'laptop-repair/<page:.*>',
'route' => 'site/laptop-repair',
'defaults' => ['page' => 'index'],
],
...
],
],
In SiteController.php I already had an action for the page which I wanted to make into a parent page:
public function actionLaptopRepair()
{
return $this->render('laptop-repair');
}
which I replaced with:
public function actionLaptopRepair($page)
{
return $this->render("/site/laptop-repair/$page");
}
The leading slash is necessary to override the default behaviour of the Yii application, which is to look for the view in 'views>{controllerName}'. For example with render('laptop-repair'); the view file laptop-repair.php would need to be in 'views>site' since the name of the controller is SiteController, whereas render("/site/laptop-repair/$page"); corresponds to a view file ($page) in 'views>site>laptop-repair'. This allows you to organise your views in subdirectories.
I created a new folder called 'laptop-repair' in 'views>site', moved the view for the parent page (laptop-repair.php) into the new directory and renamed it index.php. I put the new sub pages' view files in that new directory ('views>site>laptop-repair'), alongside the parent view (index.php).
Everything worked except for the URL creation in my nav widget. Where the following worked fine before, the 'laptop-repair' link broke after I implemented the above:
echo Nav::widget([
'options' => ['class' => 'navbar-nav ml-auto'],
'items' => [
['label' => 'Home', 'url' => ['/site/index']],
[
'label' => 'Repair Services',
'items' => [
['label' => 'Desktop PC Repairs', 'url' => ['/site/pc-repair']],
['label' => 'Laptop Repairs', 'url' => ['site/laptop-repair']],
['label' => 'Mobile Phone Repairs', 'url' => ['/site/mobile-phone-repair']],
...
The fix was simply changing the relevant line to:
['label' => 'Laptop Repairs', 'url' => ['/laptop-repair']],
Creating a link from the parent page to a sub page looks like this:
<?= Html::a('Laptop overheating?', ['laptop-repair/laptop-overheating'], ['class' => '', 'title' => 'Laptop overheating']) ?>
To add a link to the parent page to the breadcrumbs of the sub page, I replaced:
$this->title = 'Laptop Over Heating?';
$this->params['breadcrumbs'][] = $this->title;
with:
$this->title = 'Laptop Over Heating?';
$this->params['breadcrumbs'][] = ['label' => 'Laptop repair', 'url' => ['/laptop-repair']];
$this->params['breadcrumbs'][] = $this->title;
in the view file of the sub page.

yii2 Kartik-V Typeahead Basic autocomplete on name but store integer value

Updates have been made below
I am trying to use the Kartik-V Typeahead Basic widget with the Yii2 Framework.
The code below is working to display the required data, the user can search via the university name and it appears in the autocomplete list.
The issue is, the model needs to the university id, not the name. Thus the rules are this field can only store an integer and returns a validation error once you select one of the typeahead results.
<?= $form->field($model, 'university_id')->widget(TypeaheadBasic::classname(), [
'data' => ArrayHelper::map(University::find()->all(),'id','uni_name'),
'pluginOptions' => ['highlight' => true],
'options' => ['placeholder' => 'Filter as you type ...'],
]); ?>
I am hoping someone can help me understand if there is a setting that needs to be changed so when saving, the user friendly 'uni_name' data is changed back to the uni 'id'.
UPDATE:
I have gotten the code partly working thanks to "Insane Skull".
The new code is:
<?= $form->field($model, 'name')->widget(TypeaheadBasic::classname(), [
'data' => ArrayHelper::map(University::find()->all(),'id','uni_name'),
'pluginOptions' => ['highlight' => true],
'options' => ['placeholder' => 'Filter as you type ...', 'id' => 'testID'],
'pluginEvents' => [
'typeahead:select' => new yii\web\JsExpression("function(event, ui) { $('#testing123').val(ui.item.id); }"),
]
]); ?>
<?= Html::activeHiddenInput($model, 'university_id', array ('id' => 'testing123'))?>
Now I am unfortunately getting the error:
Method yii\web\JsExpression::__toString() must return a string value
I would rather use Select2 instead of Typeahead, you are basically trying to implement the functionality that already exists on Select2 but using Typeahead.
<?= $form->field($model, 'university_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(University::find()->all(),'id','uni_name'),
'options' => ['placeholder' => 'Filter as you type ...'],
]); ?>
You can use activeHiddenInput() for this purpose.
Create one public variable in model say name.
Then:
<?= $form->field($model, 'name')->widget(TypeaheadBasic::classname(), [
'data' => ArrayHelper::map(University::find()->all(),'id','uni_name'),
'pluginOptions' => ['highlight' => true],
'options' => ['placeholder' => 'Filter as you type ...'],
'select' => new yii\web\JsExpression("function( event, ui ) {
$('#id_of_hiddenField').val(ui.item.id);
}")
]); ?>
<?= Html::activeHiddenInput($model, 'university_id')?>
And in Controller Get the value of activeHiddenField.