如何在 Yii2 中创建可重用的小部件
How to create a reusable widget in Yii2
我在目前的yii2项目中制作了一个简单的小部件。简单地说,它为所有jui主题创建一个select选项列表,并允许用户更改主题并通过cookies保存。
此小部件需要两个 javascript 文件,-它们已在 运行() 中注册- 其中之一是 jquery cookie插入。我询问是否有办法保存此小部件及其 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 Extensions and AssetBundles。故事很简单,只需将一个文件夹中的所有文件放置在默认的 Yii2 文件夹之一中,例如:common、vendor。-顺便说一下,vendor 在基本和高级 yii2 应用程序的模板中都可以找到-.
除了所有文件,即 对于我的案例、小部件 class php 文件和 javascripts 文件,您还必须创建 YourWidgetNameAsset php class 文件。事实上,解决方案的关键在于 class.
我的情况
我有一个名为 JuiThemeSelectWidget 的小部件,我将它放在 vendor
目录下名为 saidbakr
的文件夹中,因此我们有 vendor\saidbakr
命名空间。该文件夹包含以下四个文件:
- JuiThemeSelectWidget.php
- JuiThemeSelectAsset.php
- JuiThemeSelect.js
- 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',
];
}
这里我们为小部件定义了 AssetBundle,类似于 this official source 中描述的内容。
现在我们来看看小部件 class 本身的 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 中描述的资产包,但在这里我们使用 $this->getView()
而不是 $this
,因为该方法不是从视图调用的。
我已经压缩了名为saidbakr
的文件夹并上传到this location or checkout this GitHub Repository,看看我做了什么,它的名字是Yii2 Extension。直接将压缩包的内容解压到vendor文件夹下名为saidbakr的文件夹,所以文件结构必须是`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();") ;?>
在 yii2 中添加小部件
在根 directory.then 中创建组件文件夹,创建 php 文件。
使用该文件中的命名空间组件(命名空间 app\components)。
包括小部件(使用 app\base\widget)。
创建扩展小部件 class 的 class
命名空间 app\components;
使用 yii\base\Widget;
创建一个视图文件夹,其中包含从小部件调用的视图文件。
我在目前的yii2项目中制作了一个简单的小部件。简单地说,它为所有jui主题创建一个select选项列表,并允许用户更改主题并通过cookies保存。
此小部件需要两个 javascript 文件,-它们已在 运行() 中注册- 其中之一是 jquery cookie插入。我询问是否有办法保存此小部件及其 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 Extensions and AssetBundles。故事很简单,只需将一个文件夹中的所有文件放置在默认的 Yii2 文件夹之一中,例如:common、vendor。-顺便说一下,vendor 在基本和高级 yii2 应用程序的模板中都可以找到-.
除了所有文件,即 对于我的案例、小部件 class php 文件和 javascripts 文件,您还必须创建 YourWidgetNameAsset php class 文件。事实上,解决方案的关键在于 class.
我的情况
我有一个名为 JuiThemeSelectWidget 的小部件,我将它放在 vendor
目录下名为 saidbakr
的文件夹中,因此我们有 vendor\saidbakr
命名空间。该文件夹包含以下四个文件:
- JuiThemeSelectWidget.php
- JuiThemeSelectAsset.php
- JuiThemeSelect.js
- 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',
];
}
这里我们为小部件定义了 AssetBundle,类似于 this official source 中描述的内容。
现在我们来看看小部件 class 本身的 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 中描述的资产包,但在这里我们使用 $this->getView()
而不是 $this
,因为该方法不是从视图调用的。
我已经压缩了名为saidbakr
的文件夹并上传到this location or checkout this GitHub Repository,看看我做了什么,它的名字是Yii2 Extension。直接将压缩包的内容解压到vendor文件夹下名为saidbakr的文件夹,所以文件结构必须是`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();") ;?>
在 yii2 中添加小部件 在根 directory.then 中创建组件文件夹,创建 php 文件。 使用该文件中的命名空间组件(命名空间 app\components)。 包括小部件(使用 app\base\widget)。 创建扩展小部件 class 的 class 命名空间 app\components; 使用 yii\base\Widget; 创建一个视图文件夹,其中包含从小部件调用的视图文件。