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

标签 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";
  }
}

最佳答案

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

除了所有文件外,即对于我的情况、小部件类 php 文件和 javascripts 文件,您还必须创建 YourWidgetNameAsset php 类文件。事实上,解决方案的关键在于该类。

我的案例

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

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

3号文件依赖于4号文件创建cookies来保存上次用户的选择。

现在我们来看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',
    ];
}

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

现在我们将看一下小部件类本身的 header 及其 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 中描述的 Assets 包但是这里我们使用了 $this->getView() 而不是 $this 因为该方法不是从 View 中调用的。

我已经压缩了名为 saidbakr 的文件夹并将其上传到 this location或查看此 GitHub Repository ,检查我做了什么,它的名字是 Yii2 Extension。直接将压缩包的内容解压到vendor文件夹下名为saidbakr的文件夹,所以文件结构必须是`vendor\saidbakr(上面列表中的四个文件),然后在你的widget中使用查看如下内容:

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

关于php - 如何在 Yii2 中创建可重用的小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28132807/

相关文章:

php - 解析爬虫的 url

mysql - 在php yii2中查询后打印特定数组值

php - 隐藏或删除下拉列表中的条目

php - 调用非对象上的成员函数bindParam()

php - 如何将所选数据保留在 <select> 元素中?超文本标记语言

javascript - OS X Javascript Widget 中 XMLHttpRequest 的空响应

ios - SF Symbols 在 iOS 15 WidgetKit 中失去了颜色

android - 如何每分钟更新一个 Android 应用小部件

javascript - yii2 ajax 验证表格

php - Yii2 下拉空选项