如何在Yii2中创建可重用的小部件

时间:2015-01-25 03:09:09

标签: php widget yii2 yii2-advanced-app

我在的当前项目中创建了一个简单的小部件。简单地说,它为所有jui主题创建一个选择选项列表,并允许用户更改主题并以cookie的形式保存。

这个小部件需要两个javascript文件, - 它们在run()中注册 - 其中一个是jquery cookies插件。我问的是如何保存这个小部件及其js文件的完整性,以便在其他Yii2项目中轻松重用,而不需要复制所有需要的js文件?

<?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";
  }
}

1 个答案:

答案 0 :(得分:11)

最后我找到了解决方案。这取决于Yii2 ExtensionsAssetBundles。故事很简单,只需将一个文件夹中的所有文件放在一个默认的Yii2文件夹中,例如:common,vendor .- 顺便说一句,在基本和高级yii2应用程序的模板中都可以找到供应商 -

除了所有文件,即 for my case ,widget类php文件和javascripts文件之外,您还必须创建YourWidgetNameAsset php类文件。实际上,解决方案的主要关键在于该类。

我的案例

我有一个名为 JuiThemeSelectWidget 的小部件我将它放在saidbakr目录下名为vendor的文件夹中,因此我们有vendor\saidbakr命名空间。该文件夹包含以下四个文件:

  1. JuiThemeSelectWidget.php
  2. JuiThemeSelectAsset.php
  3. JuiThemeSelect.js
  4. jquery.cookie.js
  5. 文件编号3取决于文件编号4,用于创建cookie以保存最后一个用户的选择。

    现在让我们看一下文件号为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',
        ];
    }
    

    在这里,我们为小部件定义了AssetBundle,类似于this official source中描述的内容。

    现在我们来看看widget类本身的标题及其run()方法:

    <?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";
      }
    }
    

    很明显,我们按this link中所述使用了资产包,但我们在这里使用了$this->getView()而不是$this,因为该方法不会从视图中调用。

    我压缩了名为saidbakr的文件夹,并将其上传到this location或结帐GitHub Repository,检查我的名字是什么 Yii2 Extension 。只需将存档的内容直接提取到名为saidbakr的文件夹,直接在vendor文件夹下,所以文件结构必须是`vendor \ saidbakr(上面列表中的四个文件),并使用你的小部件查看如下内容:

    <?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();") ;?>