kartik 树视图显示每个节点单击的不同视图

kartik tree view show different views on each node click

我正在研究 Yii2。我使用 kartik tree manager 创建了一棵树。默认情况下,在每个节点上单击它会显示 IDname 等。但我想显示其他数据。下面是我的代码

 <?=
        TreeView::widget([
            'query' => \common\models\MdcNode::find()->addOrderBy('root, lft'),
            'headingOptions' => ['label' => 'Root'],
            'rootOptions' => ['label'=>'<span class="text-primary">Root</span>'],
            'topRootAsHeading' => true, // this will override the headingOptions
            'fontAwesome' => true,
            'isAdmin' => false,
            //'nodeView' => '',
            'toolbar'           => [
                TreeView::BTN_REFRESH => false,
                TreeView::BTN_CREATE => false,
                TreeView::BTN_CREATE_ROOT => false,
                TreeView::BTN_REMOVE => false,
                TreeView::BTN_SEPARATOR => false,
                TreeView::BTN_MOVE_UP => false,
                TreeView::BTN_MOVE_DOWN => false,
                TreeView::BTN_MOVE_LEFT => false,
                TreeView::BTN_MOVE_RIGHT => false,

            ],
        'showIDAttribute' => false,
            'showTooltips' => false,

            'showNameAttribute' => false,
            'softDelete' => false,
            'cacheSettings' => ['enableCache' => true]
        ]);
        ?>

查看

更新 1

经过一些RnD我发现细节window在<div id="w0-detail" class="kv-detail-container">

在我的 JS 中,我试图隐藏它 $('#w0-detail').hide();。现在我想根据点击的不同节点显示视图。

更新 2

根据@Addi 的回答,我更新了我的代码

 <?=
    TreeView::widget([
        'query' => \common\models\MdcNode::find()->addOrderBy('root, lft'),
        'headingOptions' => ['label' => 'Root'],
        'rootOptions' => ['label'=>'<span class="text-primary">Root</span>'],
        'topRootAsHeading' => true, // this will override the headingOptions
        //'displayValue' => 1,        // initial display value
        'isAdmin' => false,
        'fontAwesome' => true,
        //'nodeView' => '',
        //show => none removes the iconType etc setting under details
        'iconEditSettings'=>['show'=>'none'],

        'toolbar' =>
            [
            TreeView::BTN_REFRESH => false,
            TreeView::BTN_CREATE => false,
            TreeView::BTN_CREATE_ROOT => false,
            TreeView::BTN_REMOVE => false,
            TreeView::BTN_SEPARATOR => false,
            TreeView::BTN_MOVE_UP => false,
            TreeView::BTN_MOVE_DOWN => false,
            TreeView::BTN_MOVE_LEFT => false,
            TreeView::BTN_MOVE_RIGHT => false,
        ],

        'showIDAttribute' => false,
        'showTooltips' => false,

        'showNameAttribute' => false,
        'softDelete' => false,
        'cacheSettings' => ['enableCache' => true],
        //removing the detail below removes the second column of view(s) 1 - 5. Section 5 is being used to render the extra data. See frontend\config\main.php later.
        'mainTemplate'=>'<div class="row">
                        <div class="col-sm-3">
                            {wrapper}
                        </div>
                        <div class="col-sm-9">
                            {detail}
                        </div>
                     </div>',
        'treeViewSettings'=> [
        'nodeView' => '@kvtree/views/_form',
        'nodeAddlViews' => [
            1 => '',
            2 => '',
            3 => '',
            4 => '',
            5 => '',
    ]]

    ]);
    ?>

现在我收到一个错误 Setting unknown property: kartik\tree\TreeView::treeViewSettings。我不知道为什么会显示此错误。我一定是遗漏了一些我不知道的东西,我坚持了下来

非常感谢任何帮助。

以下结果是在 不需要 js 隐藏细节的情况下得到的。通过隐藏细节,将不会显示 nodeAddlViews。这些节点包含在 {detail} 中。如果您要取消隐藏细节,您将在 5 个 nodeAddlViews 之一中显示额外数据。

frontend\views\krajeeproducttree\index.php

<?php
use yii\helpers\Html;
use kartik\tree\TreeView;
use frontend\models\KrajeeProductTree;

$this->title = Yii::t('app','Houses');
$this->params['breadcrumbs'][] = $this->title;
$this->params['breadcrumbs'][] = ['label' => Yii::t('app','Index'), 'url' => ['krajeeproducttree/index']];
$this->params['breadcrumbs'][] = ['label' => Yii::t('app','Refresh Database with active houses'), 'url' => ['krajeeproducttree/populate']];
?>
<div class="krajeeproducttree-index">

    <h1><?= Html::encode($this->title) ?></h1>
    
<?php  
    echo TreeView::widget([
        // single query fetch to render the tree
        'query' => KrajeeProductTree::find()->addOrderBy('root, lft'), 
        'headingOptions' => ['label' => 'Categories'],
        'fontAwesome' => true,      // optional
        'isAdmin' => false,         // optional (toggle to enable admin mode)
        'displayValue' => 1,        // initial display value
        'softDelete' => true,       // defaults to true
        'cacheSettings' => [        
            'enableCache' => true   // defaults to true
        ],
        'hideTopRoot'=>true,
        'treeOptions' => ['style' => 'height:1000px width:900px' ],
        //more detail can be added to the node
        'nodeLabel' => function($node) {
                             return $node->name;
                       },
        //disable the toolbar completely                       
        'toolbar'           => [
                TreeView::BTN_REFRESH => false,
                TreeView::BTN_CREATE => false,
                TreeView::BTN_CREATE_ROOT => false,
                TreeView::BTN_REMOVE => false,
                TreeView::BTN_SEPARATOR => false,
                TreeView::BTN_MOVE_UP => false,
                TreeView::BTN_MOVE_DOWN => false,
                TreeView::BTN_MOVE_LEFT => false,
                TreeView::BTN_MOVE_RIGHT => false,
            ],                 
        'showIDAttribute' => false,
        'showTooltips' => false,
        'showNameAttribute' => false,
        'softDelete' => false,
        'cacheSettings' => ['enableCache' => true],
        //show => none removes the iconType etc setting under details                       
        'iconEditSettings'=>['show'=>'none'],
        //remove the form buttons
        'showFormButtons'=>false,
        'breadcrumbs'=>[//'depth'=>null,
                        'glue'=>'&raquo;',
                        'activeCss'=>'kv-crumb-active',
                        'untitled'=>'Untitled'
                       ],
        //removing header below removes the search button and header                       
        //'wrapperTemplate'=>'{header}{tree}{footer}',         
        'wrapperTemplate'=>'{tree}',
        //removing the detail below removes the second column of view(s) 1 - 5. Section 5 is being used to render the extra data. See frontend\config\main.php later.
        'mainTemplate'=>'<div class="row">
                            <div class="col-sm-3">
                                {wrapper}
                            </div>
                            <div class="col-sm-9">
                                {detail}
                            </div>
                         </div>'                       
    ]); 
?>
</div>

我发现上面的 Treeview 设置,仍然打开了 {Detail} 的面包屑部分,保存和重置按钮仍然启用。

下面模型中的 isDisabled 部分特别重要,因为它不允许访问与 vendor\kartik-v\yii2-tree-manager\src\views_form.php.(第 184 行)的内置面包屑部分关联的保存和重置按钮这里:

if ($node->isDisabled()) {
        $inputOpts['disabled'] = true;
    } 

frontend\models\krajeeproducttree.php

<?php
namespace frontend\models;

use Yii;
 
class KrajeeProductTree extends \kartik\tree\models\Tree
{
    public static function getDb()
    {
        return \frontend\components\Utilities::userdb();
    }
       
    public static function tableName()
    {
        return 'works_krajee_product_tree';
    }
    
    public function isDisabled()
    {
        //so if the user is an admin he will be able to edit the tree otherwise the tree will be disabled
        //but the nodes will be clickable and section 5 will be available.
        if (Yii::$app->user->can('Manage Admin')) {
            return false;
        } else { return true; }
    }
    
    public function rules()
    {
        return [
            [['product_id','productcategory_id','productsubcategory_id'],'integer'],
            [['product_id','productcategory_id','productsubcategory_id'],'default','value'=>null], 
            [['product_id','productcategory_id','productsubcategory_id'],'safe']
        ];
    }
}

上面的模型反映了添加了 3 个外键,每个主键在它们各自的 table 中已经被添加到 Krajeeproducttree table.

下面的控制器从这 3 个 table 构建了一棵树。每次用户单击刷新面包屑时,都会重建树。

frontend\controllers\KrajeeproducttreeController.php

<?php

namespace frontend\controllers;

use frontend\models\KrajeeProductTree;
use frontend\models\Productcategory;
use frontend\models\Productsubcategory;
use frontend\models\Product;
use kartik\tree\Controllers\NodeController;
use yii\filters\VerbFilter;

class KrajeeproducttreeController extends NodeController
{
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                   // 'delete' => ['POST'],
                ],
            ],
           'access' => 
                            [
                            'class' => \yii\filters\AccessControl::className(),
                            'only' => ['index','populate'],
                            'rules' => [
                            [
                              'allow' => true,
                              'roles' => ['@'],
                            ],
                            [
                              'allow' => false,
                              'roles' => ['?'],
                            ],  
                            [
                              'allow' => true,
                              'verbs' => ['POST']
                            ],  
                            ],
            ], 
        ];
    }
        
    public function actionIndex()
    {
        return $this->render('index');      
    }
    
    public function actionPopulate()
    {
        //remove all data in the database
        KrajeeProductTree::deleteAll();
        //rebuild the database given data from productcategory ie. postcode, productsubcategory ie. street, product ie. house
        //create the root and call it Run
        $root = new KrajeeProductTree(['name'=>'Run']);
        $root->makeRoot();
        //create the postcode nodes
        $allpostcodes =[];
        $allpostcodes = Productcategory::find()->orderBy('id')->all();
        foreach ($allpostcodes as $key => $value)
        {
            $newpostcodenode = new KrajeeProductTree(['name'=>$allpostcodes[$key]['name']]);
            $newpostcodenode->productcategory_id = $allpostcodes[$key]['id']; 
            $newpostcodenode->prependTo($root);
            $allstreets = [];
            $allstreets = Productsubcategory::find()
                        ->where(['productcategory_id'=>$allpostcodes[$key]['id']])
                        ->all();
            //create the street nodes associated with this new node
            $allhouses = [];
            foreach ($allstreets as $key => $value)
            {
                $newstreetnode = new KrajeeProductTree(['name'=>$allstreets[$key]['name']]);
                $newstreetnode->productsubcategory_id = $allstreets[$key]['id'] ;
                $newstreetnode->prependTo($newpostcodenode);
                $allhouses = Product::find()
                        ->where(['productsubcategory_id'=>$allstreets[$key]['id']])
                        ->andWhere(['productcategory_id'=>$allstreets[$key]['productcategory_id']])
                        ->andWhere(['isactive'=>1])
                        ->all();
                //create the house nodes associated with this new steet node
                foreach ($allhouses as $key => $value)
                {
                    $newhousenode = new KrajeeProductTree(['name'=>$allhouses[$key]['productnumber']]);
                    $newhousenode->product_id = $allhouses[$key]['id'];
                    $newhousenode->prependTo($newstreetnode);
                }  
            }  
        }      
        return $this->render('index'); 
    }     
}

frontend\config\main.php 在模块部分下。

'treemanager' =>  [
        'class' => 'kartik\tree\Module',
        'treeViewSettings'=> [
            'nodeView' => '@kvtree/views/_form',    
            'nodeAddlViews' => [
                1 => '',
                2 => '',
                3 => '',
                4 => '',
                5 => '@app/views/krajeeproducttree/product',
        ]]    
       ],

正如 Kartik-v 所提到的,如果视图在 frontend\config\main.php.

中的 treeViewSettings 下列出,则 $node 变量由视图继承

frontend\views\krajeeproducttree\product.php

<?php
   use Yii;
   use yii\helpers\Url;
   use yii\helpers\Html;
?>
<div class="krajeeproducttree-product">
    <br>
        <?php
          if ($node->product_id > 0){
            echo Html::a('<h4>View House Details: ' .$node->name. '</h4>',Url::toRoute(['/product/view','id'=>$node->product_id]));
          }         
          if ($node->productsubcategory_id > 0){
            echo Html::a('<h4>View Street Details: ' .$node->name. '</h4>',Url::toRoute(['/productsubcategory/view','id'=>$node->productsubcategory_id]));
          }         
          if ($node->productcategory_id > 0){
            echo Html::a('<h4>View Postcode Details: ' .$node->name. '</h4>',Url::toRoute(['/productcategory/view','id'=>$node->productcategory_id]));
          }         
        ?>
    <br>
</div>

希望这对您或将来的某个人有所帮助。

对费萨尔的回应: 令人困惑...是的,product.php 只有在扩展模型中有指向它们的 table 的外部 ID 键时才有用,这样您就可以 link 带有 [=148= 的节点] 到与 table 关联的 controller/action/id。我这样做是为了避免点击每个节点时显示大量信息。

这是没有外键的控制器:

public function actionPopulate()
        {
            //remove all data in the database
            KrajeeProductTree::deleteAll();
            //rebuild the database given data from productcategory ie. postcode, productsubcategory ie. street, product ie. house
            //create the root and call it Run
            $root = new KrajeeProductTree(['name'=>'Run']);
            $root->makeRoot();
            //create the postcode nodes
            $allpostcodes =[];
            $allpostcodes = Productcategory::find()->orderBy('id')->all();
            foreach ($allpostcodes as $key => $value)
            {
                $newpostcodenode = new KrajeeProductTree(['name'=>$allpostcodes[$key]['name']]);
                $newpostcodenode->prependTo($root);
                $allstreets = [];
                $allstreets = Productsubcategory::find()
                            ->where(['productcategory_id'=>$allpostcodes[$key]['id']])
                            ->all();
                //create the street nodes associated with this new node
                $allhouses = [];
                foreach ($allstreets as $key => $value)
                {
                    $newstreetnode = new KrajeeProductTree(['name'=>$allstreets[$key]['name']]);
                    $newstreetnode->prependTo($newpostcodenode);
                    $allhouses = Product::find()
                            ->where(['productsubcategory_id'=>$allstreets[$key]['id']])
                            ->andWhere(['productcategory_id'=>$allstreets[$key]['productcategory_id']])
                            ->andWhere(['isactive'=>1])
                            ->all();
                    //create the house nodes associated with this new steet node
                    foreach ($allhouses as $key => $value)
                    {
                        $newhousenode = new KrajeeProductTree(['name'=>$allhouses[$key]['productnumber']]);
                        $newhousenode->prependTo($newstreetnode);
                    }  
                }  
            }      
            return $this->render('index'); 
        }

您会注意到子节点被添加到 ie 之前。 prependTo 父节点。您可以为您打算为其创建树的模块中的所有模型执行此操作。您还会注意到控制器是从 NodeController 扩展而来的。

Here is the format of the tables themselves.

产品类别即。邮政编码有一个 id 自动增量字段。产品子类别即。 streets 也有一个 id autoincrement 字段。此外,Productsubcategory 有一个指向 Productcategory table.

的外键 productcategory_id

产品table 即。 houses 有它的 id autoincrement 字段。此外,它还有两个外键,即。 productsubcategory_id 指向产品子类别 table。它还有一个指向产品类别 table.

的外键 productcategory_id

这个结构有助于link三个层次,也可以在上面link.

中使用上面模型中使用的Yii2的关系建模结构

每条街道 link 对应一个邮政编码,即。 productcategory_id 来自 table Productsubcategory (street) 与 Productcategory table 的 id 字段相同, 此结构还有助于检索每个节点的数据。所以下面的代码在controller links 两级:

$allstreets = Productsubcategory::find()
                            ->where(['productcategory_id'=>$allpostcodes[$key]['id']])
                            ->all();

你在frontend\config\main.php下添加了nodeView,这个有必要吗?我也找不到 ...krajeeproducttree/product 在你的代码中。

nodeView 是一个别名,与指向呈现细节的视图的路径相连,可在 vendor\kartik-v\yii2-tree-manager\src\Module 的第 81 行找到。如果config\main.php下没有提到,默认值为'@kvtree/views/_form'。 This _form is extended by the nodeAddlViews and has to exist if you want to show additional information. _form 可以修改并插入模型的视图下,但必须正确别名,例如@app \ views \krajeeproducttree \ _form.php.

现在我收到错误设置未知 属性: kartik\tree\TreeView::treeViewSettings...

treeViewSettings 不是 \vendor\kartik-v\yii2-tree-manager\src\TreeView 下列出的变量,但是在第 137 行存在 nodeView,在第 153 行存在 nodeAddlViews,因此您可以单独使用这些变量。 IE。不在您选择构建的每个单独树的 treeViewSettings 中。

我在你的代码中也找不到.....krajeeproducttree/product...

是的,控制器 KrajeeproductreeController 应该有一个名为 product 的操作来调用产品视图 product.php。这通常是预期的,但如果您在为 nodeAddlViews 创建的任何视图中执行 var_dump($node),您将获得 $node 的数组。通常你必须在控制器中传递一个带有渲染的参数,例如。

return $this->render('index', [
            'node' => $node
        ]); 

但是 Krajee 在这里提到了您自动获得此信息的事实。

上面的每个视图都将直接接收并读取与上面 nodeView 部分中提到的相同的参数(例如,这些视图将以 $node、$modelClass、$action 等形式提供给视图.).此外,views还会接收到$form参数,即ActiveForm实例(来自kartik-v/yii2-widget-activeform)。

所以没有必要采取行动。 $node值在这里生成:

供应商文件夹中 TreeView 中的第 1211 行

public function renderDetail()
    {
        /**
         * @var Tree $modelClass
         * @var Tree $node
         */
        $modelClass = $this->query->modelClass;
        $node = $this->displayValue ? $modelClass::findOne($this->displayValue) : null;
        if (empty($node)) {
            $node = new $modelClass;
        }

渲染细节时创建 $node 值。