How to create a reusable widget in Yii2

I made a simple widget in my current yii2 project. It simply creates a list of selection options for all jui themes and allows the user to change the theme and save it as cookies.

Two javascript files are needed for this widget, they are registered in run () - one of them is the jquery cookie plugin. I ask about how to preserve the integrity of this widget and its js files in order to facilitate reuse in other Yii2 projects without the need, maunally, to copy all the necessary js files?

<?php namespace common\libs; use yii; use yii\base\Widget; use yii\web\View; use yii\web\JqueryAsset; /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ /** * Description of JuiThemeSelectWidget * * @author Said Bakr */ class JuiThemeSelectWidget extends Widget { private $list; private $script; private static $juiThemeSelectId = 'JuiThemesList'; public $themeListId; public $label; public function init() { parent::init(); if ($this->themeListId) self::$juiThemeSelectId = $this->themeListId; $this->list = $this->createSelectList($this->getThemesList()); $this->makeScript(); } public static function getThemesList() { $themesPath = dirname(Yii::$app->basePath).DIRECTORY_SEPARATOR."vendor".DIRECTORY_SEPARATOR."bower".DIRECTORY_SEPARATOR."jquery-ui".DIRECTORY_SEPARATOR."themes"; $output = []; foreach (scandir($themesPath) as $item){ if (is_dir($themesPath.DIRECTORY_SEPARATOR.$item) && ($item != '.' && $item !='..')) $output[] = $item; } return $output; } public static function createSelectList($items) { $juiThemeSelectId = self::$juiThemeSelectId; $output = ''; $output .= "<select id=\"$juiThemeSelectId\">"."\n"; foreach ($items as $item){ $output .= "<option value='$item'>$item</option>\n"; } $output .= "</select>\n"; return $output; } /** * Making the client-side script for the list */ private function makeScript() { $t = self::$juiThemeSelectId; $this->script = <<<EOD <script> var juiThemeSelectId = "$t" </script> EOD; } public function run() { parent::run(); $this->getView()->registerJsFile('/myjs/jquery.cookie.js', ['depends' => [JqueryAsset::className()]]); $this->getView()->registerJsFile('/myjs/JuiThemeSelect.js', ['depends' => [JqueryAsset::className()]]); return "$this->label $this->list \n $this->script"; } } 
+8
php yii2 widget yii2-advanced-app
source share
2 answers

Finally, I found a solution. It depends on the Yii2 and AssetBundles extensions . The story is simple, just make all the files in one folder, placed in one of the Yii2 default folders, for example: common, vendor. - By the way, the provider is found in both the base and the advanced application template yii2.

In addition to all the files, that is, for my case, the widget php file and javascripts files, you need to create a php class file YourWidgetNameAsset. Indeed, the main key to the solution lies in this class.

My case

I have a JuiThemeSelectWidget widget that I placed in a folder called saidbakr in the vendor directory, so we have a vendor\saidbakr . This folder contains the following four files:

  • JuiThemeSelectWidget.php
  • JuiThemeSelectAsset.php
  • JuiThemeSelect.js
  • jquery.cookie.js

File number 3 depends on file 4 for creating cookies in order to save the user's last choice.

Now we see the code of file 2 JuiThemeSelectAsset.php :

 <?php namespace vendor\saidbakr; use yii\web\AssetBundle; /* * It is free for use and modify with one simple rule: * regarding credits for the author either it modified or not * Author: Said Bakr. said_fox@yahoo.com * http://2index.net */ /** * Description of Kabb * * @author Said */ class JuiThemeSelectAsset extends AssetBundle { public $sourcePath = '@vendor/saidbakr'; public $autoGenerate = true; /** * @inheritdoc */ public $js = ['jquery.cookie.js','JuiThemeSelect.js']; public $depends = [ 'yii\jui\JuiAsset', ]; } 

Here we defined an AssetBundle for a widget similar to that described in this official source .

Now we look at the title of the widget class itself and its run() method:

 <?php namespace vendor\saidbakr; use yii; use yii\base\Widget; //use yii\web\View; //use yii\web\JqueryAsset; class JuiThemeSelectWidget extends Widget { // ...... Class code.... public function run() { parent::run(); JuiThemeSelectAsset::register($this->getView()); return "$this->label $this->list \n $this->script"; } } 

It’s clear that we used the asset package as described in this link , but here we used $this->getView() instead of $this , because the method is not called from the view.

I compressed the folder named saidbakr and uploaded it to this location or pulled out this GitHub Repository to check what I did, whose name is Yii2 Extension . Just extract the contents of the archive into a folder named saidbakr right below the provider folder. Thus, the file structure should be "vendor \ saidbakr" (the four files discussed in the list above), and use the widget in your views something like this:

 <?php use yii\helpers\Html; use yii\widgets\ActiveForm; use yii\jui\DatePicker; use vendor\saidbakr\JuiThemeSelectWidget; ?> <div> <?= JuiThemeSelectWidget::widget(['label' => 'Select New JUI Theme', 'themeListId' => 'fox']) ;?> <div class="profile-form"> </div> <h2>Testing Elements for the JUI</h2> <form> <select id="sel"> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> </select> </form> <?php $this->registerJs("$('#sel').selectmenu();") ;?> 
+11
source share

Add widget to yii2 Create a component folder inside the root directory. Then create a php file. use the namespace components in this file (namespace application \ components). enable the widget (use the application \ base \ widget). Create a class that extends the class. Widget namespace app \ components; use yii \ base \ Widget; Create a views folder containing a view request from the widget.

+1
source share

All Articles