简体   繁体   English

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

[英]How to create a reusable widget in Yii2

I have made a simple widget in my current project of . 我在当前的项目中了一个简单的小部件。 Simply, it creates a select options list for all jui themes and allow the user to change the theme and save it by the mean of cookies. 简单地说,它为所有jui主题创建一个选择选项列表,并允许用户更改主题并通过cookie的方式保存。

This widget need two javascript files, - they are registered in run() - one of them is the jquery cookies plugin. 这个小部件需要两个javascript文件, - 它们在run()中注册 - 其中一个是jquery cookies插件。 I ask about the being of way to save integrity of this widget and its js files to make it easy to be reused in other Yii2 projects without the need for, maunally, copying all the needed js files? 我问的是如何保存这个小部件及其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";
  }
}

Finally I have found the solution. 最后我找到了解决方案。 It depends on Yii2 Extensions and AssetBundles . 它取决于Yii2 ExtensionsAssetBundles The story is simple, just make all files in one folder placed in one of default Yii2 folders, for example: common, vendor.- By the way, vendor is found in both basic and advanced yii2 application's template -. 故事很简单,只需将一个文件夹中的所有文件放在一个默认的Yii2文件夹中,例如:common,vendor.- 顺便说一下,供应商可以在基本和高级yii2应用程序的模板中找到 - 。

In addition to all files, ie for my case , the widget class php file and the javascripts files, you have to create YourWidgetNameAsset php class file. 除了所有文件,即我的情况 ,widget类php文件和javascripts文件,你必须创建YourWidgetNameAsset php类文件。 Indeed, the master key of the solution lies in that class. 实际上,解决方案的主要关键在于该类。

My case 我的情况

I have a widget named JuiThemeSelectWidget I placed it inside a folder named saidbakr under vendor directory so we have vendor\\saidbakr namespace. 我有一个名为JuiThemeSelectWidget的小部件我将它放在vendor目录下名为saidbakr的文件夹中,因此我们有vendor\\saidbakr命名空间。 That folder contains the following four files: 该文件夹包含以下四个文件:

  1. JuiThemeSelectWidget.php JuiThemeSelectWidget.php
  2. JuiThemeSelectAsset.php JuiThemeSelectAsset.php
  3. JuiThemeSelect.js JuiThemeSelect.js
  4. jquery.cookie.js jquery.cookie.js

The file number 3 depends on the file number 4 for creating cookies to save the last user's choice. 文件号3取决于文件号4,用于创建cookie以保存最后一个用户的选择。

Now lets we see the code of file number 2 JuiThemeSelectAsset.php : 现在让我们看一下文件号为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 AssetBundle for the widget something similar to described in this official source . 在这里,我们为小部件定义了AssetBundle,类似于官方来源中描述的内容。

Now we will take a look at the header of the widget class itself and its run() method: 现在我们来看看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";
  }
}

It is clear that we used the asset bundle as described in this link but here we used $this->getView() instead of $this because the method does not invoked from a view. 很明显,我们使用了此链接中描述的资产包,但在这里我们使用$this->getView()而不是$this因为该方法不会从视图中调用。

I have compressed the folder named saidbakr and uploaded it to this location or checkout this GitHub Repository , to check what have I made which its name is Yii2 Extension . 我已压缩名为saidbakr的文件夹并将saidbakr上传到此位置或检出此GitHub存储库 ,以检查我做了什么,其名称为Yii2 Extension Just extract the contents of the archive to folder named saidbakr directly under vendor folder, So the file structure must be `vendor\\saidbakr(the four files regarded in the list above) , and use the widget in your views something like the following: 只需将存档的内容直接提取到vendor文件夹下名为saidbakr的文件夹中, 因此文件结构必须是`vendor \\ _edbakr(上面列表中的四个文件) ,并在视图中使用小部件,如下所示:

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

Add Widget in yii2 Create components folder inside root directory.then create php file. 在yii2中添加Widget在根目录下创建组件文件夹。然后创建php文件。 use namespace components in that file(namespace app\\components). 在该文件中使用命名空间组件(命名空间app \\ components)。 include widget (use app\\base\\widget). 包含小部件(使用app \\ base \\ widget)。 Create class that extends Widget class namespace app\\components; 创建扩展Widget类命名空间app \\ components的类; use yii\\base\\Widget; 使用yii \\ base \\ Widget; Create a views folder that contains view file calling from widget. 创建一个views文件夹,其中包含从widget调用的视图文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM