Yii 1.1: nestedtree

Complex solution to handle Nested set in tree view
17 followers

My plain was developing a complex solution to handle Nested set model in tree view. This widget is a wrapper for jQuery dynaTree plugin, and there are a controller for ajax requests, and an extended ActiveRecord maintain model nested set and other properties.
After a quick installation process you can use a widget to create, delete and sort an items according to the nested set.

Requirements

Yii 1.1 or above

Description

dynaTree Widget

The main component of the extension is the widget as a wrapper for dynTree jQuery plugin. It was inspired by broker dynatree extension (http://www.yiiframework.com/extension/dynatree/). Thanks! Really good work!

I extended this wrapper widget with the following functions:
- AJAX load items from nested set model
- create new item
- delete active item
- sort items using Drag&Drop
- handle click event on the item

Nested set model

Nested set model is not a part of this description. I use (and of course extended) nestedsetbehavior ( http://www.yiiframework.com/extension/nestedsetbehavior) extension.

I extended this behavior som extra functions:
- titleAttribute property title attribute of the tree (default 'name')
- getNodeTitle() method get title of the tree item using titleAttribute.
- getTree() method get tree data from model in json
- getNextMaxValue() method to get title next max value (if title is unique)

I'd rather extends original Yii class (CActiveRecord) with new methods, than use behaviors. Therefore I attached NestedTreeActiveRecord.php as an extended class of ActiveRecord , but there are the two neccessary behavior, an original NestedSetBehavior and DynaTreeBehavior containing the extra functions.(see Installation).

The default shema of a model is attached (table-shema.sql). It is important, that there have to be minimum one root element in the table!

AJAX actions and controller

To handle AJAX callback functions use my controller (AxController). It has four public methods Load(), Insert(), Move(), and Delete(). This Controller is global, you can use it with any nested set model, specified previous section.
Actions wait for a POST request with model class name and other params (widget prepare it) and send back validated result to the widget.

CSRF validation implemented and automatic connected to the AJAX actions POST data.

Installation

First copy downloaded files to /protected/extension folder.

config/main.php

Import extension to the application. If you would use my Ajax Controller, and the default AJAX actions of the widget, just add my controller to the controllerMap named AXtree:

return array(
   'import' => array(
        ...
        'application.extensions.NestedDynaTree.*',
    ),
    'controllerMap'=>array(
        'AXtree'=>'ext.NestedDynaTree.AXcontroller'
    ),
    ....
    'components'=>array(
       //Uncomment the following line If you want to CSRF validation activate 
      /* 'request'=>array(
            'enableCsrfValidation'=>true,
        ),
      */
     ...
 }

Be careful with CSRF validation, because from that point all of your POST request will be validated! See documentation of Yii CSRF validation!!

model configuration

Create or use model having nested set attributes (lft,rgt,level). Extend model to NestedTreeActiveRecord or implement behaviors.

If you use NestedTreeActiveRecord, and following attribute name in your model is different from default you have to set up :
- leftAttribute (default 'lft')
- rightAttribute (default 'rgt')
- levelAttribute (default 'level')
- titleAttribute (default 'name')

The configuration is very simple:

class myModelClass extends NestedTreeActiveRecord {
 
       public $leftAttribute = 'different_left_attributename';

If you want to use behaviors inside your ActiveRecord model put this code to your model class:

class myModelClass extends CActiveRecord{
 
   ...
    public function behaviors() {
        return array(
            'NestedSetBehavior' => array(
                'class' => 'ext.NestedDynaTree.NestedSetBehavior',
                'leftAttribute' => 'lft',
                'rightAttribute' => 'rgt',
                'levelAttribute' => 'level',
            ),
            'DynaTreeBehavior' => array(
                'class' => 'ext.NestedDynaTree.NestedTreeBehavior',
                'titleAttribute' => 'name'
            )
        );
    }
   ...

Use behaviors only if you don't want to use NestedTreeActiveRecord !! NestedTreeActiveRecord contains all neccessary methods, and behaviors!!!

You can Override method getTitle() in the model class, if you would like show different title value (like count element in the item).

AJAX controller configuration

If you want to use my Controller (recommended), just add AXcontroller to the controllerMap.
If us don't want to use controllerMap you can set the controller absolute url (url to /extensions/NestedDynaTree/AXContorller ) in the widget 'ajaxController' option (default '/AXtree/').

Usage

<?php
        $this->widget('ext.NestedDynaTree.NestedDynaTree', array(
            //the class name of the model.
            'modelClass' => "Cathegories",
            // action taken on click on item. (default empty)
            'clickAction' => "/Cathegories/update/",
            //if given, AJAX load a result of clickAction to the container (default empty)
            'clickAjaxLoadContainer' => 'content',
            //can insert, delete and ( if enabled)drag&drop (default true) 
            'manipulationEnabled' => !Yii::app()->user->isGuest,
            //can sort items by drag&drop (default true)
            'dndEnabled' => true,
 
            //AJAX controller absolute path if you don`t use controllerMap
            // 'ajaxController'=>'/path/to/controller/' //default('/AXtree/')
        ));
        ?>

Important info !!!

Some enviroment (mainly localhost) it is recommended using an ajaxController option in this format:

'ajaxController' => Yii::app()->baseUrl . '/AXtree/'

Thanks waterloomat for the post!! Next relase will serve this issue!

Your own AJAX controller

If you'd like to use your own controller, and actions, you can set in the widget configuration following actions:
- ajaxController :path to your controller default ('/AXtree/')
- loadAxAction: Action name to load tree in json
- insertAxAction: Action name to insert nem item
- deleteAxAction: Action name to delete active item
- clickAction: Action name taken when click on the item.

(if clickAjaxLoadContainer property is set, clickAction will be loaded via AJAX to the container)

Actions and parameters

load action
POST data required:
- model:name of the model class,
- clickAction:action taken user click
RETURN: items array in json format

insert action
POST data required:
- model:name of the model class,
- source:active item pk,
- mode: inserting mode (after,over)
RETURN:
- status: true if success or if not success errortext,
- key: pk of the new item

delete action
POST data required:
- model:name of the model class,
- source:active item pk (if comfirmed to delete),
RETURN:
- status: true if success or if not success errortext,
- key: pk of the next item have to be activated

move action
POST data required:
- model:name of the model class,
- source:active item pk (dragged item),
- target:item pk (dropitem), - mode: inserting mode (before,after,over)
RETURN:
- status: true if success or if not success errortext,
- sourceNode: pk of the item have to be activated

Summary

This is the initial version of the extension. I want to improve functionality and iternationalisation, and some other good stuff include to it.

Please inform me any bugs, problems, or need to increase this extension performance in the topic of this extension !

Total 2 comments

#18701 report it
moo.tensai at 2014/12/14 09:42am
Best Solution For Nested Yii 1

Solved my problem!

Really great! Thanks for this extension

#12037 report it
yonghan at 2013/02/22 12:39pm
It's great

Thanks for the extension. :)

Leave a comment

Please to leave your comment.

Create extension