treeview - Yii2 显示/隐藏kartik树视图节点
问题描述
我正在使用Kartik 树管理器。我能够添加、删除、更新节点。还有更多要求,即根据用户访问权限显示/隐藏节点。即,当给用户一个特定节点时,只应显示具有所有子节点(如果有)的特定节点。
到目前为止我做了什么?
我创建了一个表user-node
,我在其中将节点 ID 分配给用户,如下所示
我想做的事
现在我只想显示指定节点及其子节点,并向该用户隐藏其他节点
控制器
目前,我正在渲染树结构的视图有两种,但将来会更多
我的首页
public function actionIndex() { if(Yii::$app->user->isGuest){ $this->redirect(Yii::$app->urlManager->createUrl('site/login')); } return $this->render('index'); }
本身树管理器节点控制器
/** * View, create, or update a tree node via ajax * * @return mixed json encoded response */ public function actionManage() { static::checkValidRequest(); $data = static::getPostData(); $nodeTitles = TreeSecurity::getNodeTitles($data); $callback = function () use ($data, $nodeTitles) { $id = ArrayHelper::getValue($data, 'id', null); $parentKey = ArrayHelper::getValue($data, 'parentKey', ''); $parsedData = TreeSecurity::parseManageData($data); $out = $parsedData['out']; $oldHash = $parsedData['oldHash']; $newHash = $parsedData['newHash']; /** * @var Module $module * @var Tree $treeClass * @var Tree $node */ $treeClass = $out['treeClass']; if (!isset($id) || empty($id)) { $node = new $treeClass; $node->initDefaults(); } else { $node = $treeClass::findOne($id); } $module = TreeView::module(); $params = $module->treeStructure + $module->dataStructure + [ 'node' => $node, 'parentKey' => $parentKey, 'treeManageHash' => $newHash, 'treeRemoveHash' => ArrayHelper::getValue($data, 'treeRemoveHash', ''), 'treeMoveHash' => ArrayHelper::getValue($data, 'treeMoveHash', ''), ] + $out; if (!empty($data['nodeViewParams'])) { $params = ArrayHelper::merge($params, unserialize($data['nodeViewParams'])); } if (!empty($module->unsetAjaxBundles)) { $cb = function ($e) use ($module) { foreach ($module->unsetAjaxBundles as $bundle) { unset($e->sender->assetBundles[$bundle]); } }; Event::on(View::class, View::EVENT_AFTER_RENDER, $cb); } TreeSecurity::checkSignature('manage', $oldHash, $newHash); return $this->renderAjax($out['nodeView'], ['params' => $params]); }; return self::process( $callback, Yii::t('kvtree', 'Error while viewing the {node}. Please try again later.', $nodeTitles), null ); }
我怎样才能实现它?任何帮助将不胜感激。
解决方案
实现隐藏/显示某些节点的一种方法可能如下:
在视图中你应该有你的数据库表名。
查找您感兴趣的表名。
在表名的文件夹内应该有类似的文件名:_form.php、_script.php 和 index.php
index.php 文件应该有一些用途,其中应该有: ...
使用kartik\tree\TreeView;
使用kartik\tree\Module;
...
在这些 use 语句之后,您可以添加以下代码:
/** @var 整数 $uid */
// get current logged in user id. // this is used to control showing tree content, and // to control form fields. if (isset(Yii::$app->user)) { $uid = Yii::$app->user->getId(); }
所以现在登录的用户 id 保存在变量 $uid 中
在同一个 index.php 文件中,您应该有呈现树视图的代码。开头是:echo TreeView::widget
在此 TreeView::widget([.. 中,您可以添加一个查询,该查询仅呈现当前登录的用户内容,如下所示:
'query' => YourTableName::find()->where(['user_id' => $uid])->addOrderBy('root, lft'),
... 其他设置 ...
如果您希望管理员查看或更改内容,您可以添加一个控制器,例如名为 AdminController,然后在这个 index.php TreeView::widget 中您可以添加更多选项,如下所示:
echo TreeView::widget([
'query' => YourTableName::find()->where(['user_id' => $uid])->addOrderBy('root, lft'),
'headingOptions' => ['label' => 'YourLableName'],
//'rootOptions' => ['label' => '<span class="text-success">Root</span>'],
'fontAwesome' => false,
'isAdmin' => true,
'showInactive' => AdminController::isAdmin(),
'displayValue' => 0,
'showIDAttribute' => true,
'emptyNodeMsg' => ' type some msg here ... .',
'showCheckbox' => false,
'multiple' => false,
'options' => ['id' => 'treeID'],
'allowNewRoots' => false,
'toolbar' => [
'create' => ['alwaysDisabled' => true],
//'remove' => ['alwaysDisabled' => !(AdminController::isAdmin())],
// 'move-up' => ['alwaysDisabled' => !(AdminController::isAdmin())],
// 'move-down' => ['alwaysDisabled' => !(AdminController::isAdmin())],
// 'move-left' => ['alwaysDisabled' => !(AdminController::isAdmin())],
// 'move-right' => ['alwaysDisabled' => !(AdminController::isAdmin())],
//'remove' => false,
],
'cascadeSelectChildren' => false,
//'softDelete' => false,
'iconEditSettings'=> [
'show' => 'list',
'listData' => [
// 'folder' => 'Folder',
'file' => 'File',
'star' => 'Star',
'bell' => 'Bell',
// 'phone' => 'Phone',
]
],
'cacheSettings' => ['enableCache' => true],
'nodeAddlViews' => [
Module::VIEW_PART_1 => '@app/views/mappings/_form',
],
]);
这只是一个小小的开始,但您可以更进一步。例如,假设用户未登录或假设您想以任何方式显示某些节点。在这些情况下,您可以使用 switch case 语句并检查例如 $uid 是否未定义(未设置,因为用户未登录)在这种情况下,您可以要求用户登录或呈现或显示不同的树视图:
switch ($SomeVariable) { case "case_to_check": echo TreeView::widget([ ... 'query' => TableName::find()->where(['user_id' => $uid])->addOrderBy( 'root, lft'), ... break;
case "another_case": echo TreeView::widget([ ... break; 默认值: echo TreeView::widget([ ...
== 您也可以在 index.php 的顶部添加 html select,如下所示:
<select name="Give_any_name_you_like" size=1 class="btn btn-primary" style="margin-bottom: 0.5em; margin-left: 0.5em; ">
<option value="0">Select Node</option>
<option value="1">mynodes</option>
<option value="2">othernodes</option>
<option value="3">allnodes</option>
</select>
然后使用java脚本过滤和捕获选定的值,然后你可以在switch case中使用这个vale来显示某些节点。您可以将 java 脚本代码放在 <?php 块中,在 switch case 或 echo TreeView::widget([ 之前。java 脚本代码可能如下所示:
$this->registerJs("
$('select[name=" . "The_name_you_give_in_select" . "]').change(function(){
var value = $(this).val();
switch(value) {
case '1':
window.location.href = \"your-page-name?what=mynodes\" ;
break;
case '2':
window.location.href = \"your-page-name?what=othernodes\" ;
break;
default:
window.location.href = \"your-page-name?what=allnodes\" ;
}
});", View::POS_READY);
=== 然后你检查什么在 switch case 中的值并使用它来过滤要显示的树节点。类似这段代码的代码就在 java 脚本代码上方:
/** @var integer $The_name_you_give_in_select */
// get value from selection menu.
// this is used to filter and show desired tree.
if (isset($_GET['what'])) {
$The_name_you_give_in_select = $_GET['what'];
} else {
$The_name_you_give_in_select = "defaultcase";
}
// Then in switch case:
switch ($The_name_you_give_in_select) {
case "mynodes":
echo TreeView::widget([
...
break;
Case "othernodes":
echo TreeView::widget([
...
break;
default:
echo TreeView::widget([
...
============= === 你也可能想在views/your_table_name/_form.php中做一些改变
在 _form.php 中,您还可以控制要显示的字段,使哪些字段可编辑或只读等,如下所示: == _form.php:
... /** @var 整数 $userid */
// save current node user id in var $userid // to be used to control form fields $userid = $node->user_id; ... if(isset($userid)){ $username = Yii::$app->user->identity; } ... <div class="your-form"> ... <?= $form->field($node, 'annotation')->textarea(['rows' => 6, 'readonly' => !(Yii::$app->user->identity->id == $userid or AdminController::isAdmin())]) ?> <?= $form->field($node, 'comments')->textarea(['rows' => 6, 'readonly' => !(Yii::$app->user->identity->id == $userid or AdminController::isAdmin())]) ?> <!-- <?/*= $form->field($username, 'username')->textInput(['maxlength' => true, 'readonly'=>true])->label('Created by User') */?>--> <?= $form->field($node, 'user_id')->textInput(['readonly'=>true]) ?> <?= $form->field($node, 'date_added')->textInput(['placeholder' => 'Date Added', 'readonly'=>true]) ?> </div>
========= === AdminContoler.php 可能看起来像这样:
<?php
namespace app\controllers;
use Yii;
...
class AdminController extends Controller
{
/**
*
* manage admins.
* add admins here
* this will allow admins more control on all tables, but not accessing and managing users
* controlling, accessing and managing users is configured through:
* - config/web.php and views/layouts/main.php
* - (1) in config/web.php go to modules -> user -> admins and add username(s)that you want to be admin accessing and managing users
* - (2) THEN in view views/layouts/main.php, follow the same logic in line 62 and add username(s).
*
* @return bool
*/
public static function isAdmin()
{
if (
Yii::$app->user->identity->username == 'type user name here'
or
Yii::$app->user->identity->username == 'type user name here'
// add more here for example by uncommenting the following lines and typing username that you want to be admin
// or
// Yii::$app->user->identity->username == 'type user name here'
// or
// Yii::$app->user->identity->username == 'type user name here'
// or
// Yii::$app->user->identity->username == 'type user name here'
) {
return true;
} else {
return false;
}
}
}