Yii 1.1: nestedsetadmingui

Nested Set Model Administration GUI with jsTree plugin.


  • Gii Model and Crud templates that generate a graphical user interface (tree) for nested set model administration.With the help of jstree and fancybox plugins,all CRUD operations on a nested set model are reduced to context menu selections.Available operations appear in a context menu which opens when a node in the tree is right clicked.Nodes can be moved around in the tree with simple drag and drop actions.The overall feel approximates a desktop experience.


Tested with Yii 1.8,will probably work with older versions too.


  • Hide index.php from your requests,if you have'nt done so yet.You can find detailed instructions on how to do this here.(Paragraph 6). Also,in urlManager configuration in config/main.php file set
  • Unzip the downloaded file.
    • Copy the gii folder to your application's protected folder.
    • Copy the js_plugins folder to the root folder of your application,(same level as protected).
    • Copy the client_val_form.css file and images folder to your application's css folder.
    • Copy the nestedBehavior folder to your application's extensions folder.
  • In config/main.php file,in gii configuration, add the path of your gii folder like so:
            // If removed, Gii defaults to localhost only. Edit carefully to taste.
                        'generatorPaths' => array(
                        'application.gii'  //nested set  Model and Crud templates

Demo Installation (Optional)

  • Open the Demo Folder.
  • Import product_table.sql and categorydemo_table.sql in your database.
  • Copy the models,controllers,and view files found in the Demo folder to the corresponding folders of your application.
  • Navigate to [application root]/categorydemo] and you should see the administration page.


  • Prepare your Nested Set Model table structure. Use the contents of nestedSetAdminGUI.sql file as a basis.All columns stated in this file are required for the extension to work-you can add your own columns.You can change the name of the table,it will become the model class name in the generated files.

IMPORTANT:Use a simple name for the table,all lowercase and no underscores,hyphens and the like.

  • Import the table in your database.
  • Navigate to gii page ([application root]/gii).
  • Click Model Generator.
  • Type the table name in the Table Name field.
  • Click on the Code Template and select nested.Preview if you want,and then Generate.
  • Your nested set Model class has been generated.

IMPORTANT:Open the newly generated model class file and remove ALL rules associated with Nested Set Behavior columns: rgt,lft,root,level,id.No rules should appear for these columns.

  • Click Crud Generator
  • In the Model Class field type the name of the class that was generated in the previous step.
  • Again,click Code template and select nested,if it's not already selected.
  • Preview if you want,and then Generate.
  • This is it.Navigate to the controller URL .For example if you used the default table name category,go to [application root]/category.You should see the administration page and you are ready to create roots and nodes.

Cheers. Spiros "DrumAddict" Kabasakalis,September 5th 2011.


Total 14 comments

#14226 report it
gb5256 at 2013/07/28 06:13am
did anybody tried out the successor of this?

Hello out there, I am right now testing the new version of this extension, which is here http://www.yiiframework.com/extension/jstree-behavior/ I have some troubles with it, for example the demo files that come with it are not working. Some actions work (like rename, delete) but other not at all, like add node, add root. Does anybody managed to get this to work? Or is this not an extension, but more a extension in beta? gb5256

#10520 report it
__construct() at 2012/11/01 04:50pm
How to make "create root" button finally work

in views/categorydemo/_form.php you need to make several bug fixes

Here is the fixed "_form.php" version.

<div id="categorydemo_form_con"   class="client-val-form">
<?php if ($_POST['create_root']=='true' && $model->isNewRecord) : ?>              <h3 id="create_header">Create New Root Categorydemo </h3>
<?php elseif ($model->isNewRecord) : ?>     <h3 id="create_header">Create New Categorydemo </h3>
     <?php  elseif (!$model->isNewRecord):  ?>     <h3 id="update_header">Update Categorydemo <?php  echo $model->name;  ?> (ID:<?php   echo $model->id;  ?>) </h3>
    <?php   endif;  ?>
    <div   id="success-categorydemo" class="notification success png_bg" style="display:none;">
                <a href="#" class="close"><img src="<?php echo Yii::app()->request->baseUrl.'/css/images/icons/cross_grey_small.png';  ?>"
                                                                title="Close this notification" alt="close" /></a>
<div  id="error-categorydemo" class="notification errorshow png_bg" style="display:none;">
                <a href="#" class="close"><img src="<?php echo Yii::app()->request->baseUrl.'/css/images/icons/cross_grey_small.png';  ?>"
                                                                title="Close this notification" alt="close" /></a>
<div class="form">
<?php   $formId='categorydemo-form';
              ( ($_POST['create_root']!='true')?CController::createUrl('categorydemo/create'):CController::createUrl('categorydemo/createRoot')):
$val_error_msg='Error.Categorydemo was not saved.';
( ($_POST['create_root']!='true')?'Categorydemo was created successfuly.':'Root Categorydemo was created successfuly.'):
                                                  'Categorydemo was updated successfuly.';
    var response= jQuery.parseJSON (data);
    if (response.success ==true)
        .fadeOut(1000, "linear",function(){
                                                            .append("<div> '.$val_success_message.'</div>")
                                                            .fadeIn(2000, "linear")
        //isset($updatesuccess) ? $updatesuccess : '' .
         else {
                    .css({"opacity": 1 })
$js_afterValidate="js:function(form,data,hasError) {
        if (!hasError) {                         //if there is no error submit with  ajax
                         return false; //cancel submission with regular post request,ajax submission performed above.
    } //if has not error submit via ajax
return false;       //if there is validation error don't send anything
    }                    //cancel submission with regular post request,validation has errors.
$form=$this->beginWidget('CActiveForm', array(
  // 'enableAjaxValidation'=>true,
     'errorMessageCssClass' => 'input-notification-error  error-simple png_bg',
                                        'errorCssClass' => 'err',
                                        'successCssClass' => 'suc',
                                        'afterValidateAttribute' => 'js:function(form, attribute, data, hasError){
                                                                      }else {
<?php echo $form->errorSummary($model, '<div style="font-weight:bold">Please correct these errors:</div>', NULL, array('class' => 'errorsum notification errorshow png_bg')); ?><p class="note">Fields with <span class="required">*</span> are required.</p>
 <div class="row" >
  <?php echo $form->labelEx($model,'name'); ?>    <?php  echo $form->textField($model,'name',array('size'=>60,'maxlength'=>128,'value'=>isset($_POST['name']) ? $_POST['name'] : '','style'=>'width:88%;'));  ?>       <span  id="success-Categorydemo_name"  class="hid input-notification-success  success png_bg"></span>
    <div><small></small> </div>
     <?php   echo $form->error($model,'name');  ?>    </div>
    <div class="row">
        <?php echo $form->labelEx($model,'description'); ?>
        <?php echo $form->textArea($model,'description',array('rows'=>6, 'cols'=>50)); ?>
             <span  id="success-Categorydemo_description"  class="hid input-notification-success  success png_bg"></span>
           <div><small></small> </div>
        <?php echo $form->error($model,'description'); ?>
<input type="hidden" name= "YII_CSRF_TOKEN" value="<?php echo Yii::app()->request->csrfToken; ?>"  />
  <input type="hidden" name= "parent_id" value="<?php echo isset($_POST['parent_id']) ? $_POST['parent_id'] : 0; ?>"  />
  <?php  if (!$model->isNewRecord): ?>    <input type="hidden" name= "update_id" value=" <?php echo isset($_POST['update_id']) ?$_POST['update_id'] : 0; ?>"  />
     <?php endif; ?>      
   <div class="row buttons">
 <?php   echo  CHtml::submitButton($model->isNewRecord ? 'Submit' : 'Save',array('class' => 'button align-right')); ?>  </div>
 <?php  $this->endWidget(); ?></div><!-- form -->
<script  type="text/javascript">
 //Close button:
            function () {
                $(this).parent().fadeTo(400, 0, function () { // Links with the class "close" will close parent
                return false;
#10516 report it
__construct() at 2012/11/01 04:00pm
Error in demo code


this string

url:"<?php echo baseUrl; ?>/product/productList",

shoud be replaced with this:

url:"<?php echo $baseUrl; ?>/product/productList",
#10253 report it
cappadochian at 2012/10/14 05:41pm
create root not happens


new installation with yii 1.1.12.

I don't know why but now it's not working again. I have set error_reporting, I have done everything like in instructions. first run (assets dir empty), firebug:


create root:

TypeError: $.fancybox is not a function
"onClosed":    function(){

second run (assets dir NOT empty), firebug:


I've checked fancybox dir, it was empty. I've replaced missing files of fancybox. rerun, seems fine.

create root (by children is also the same):

Create New Root
Root was created successfuly.

but name field is empty.

right-click/rename/firebug (by left-click is also the same):

TypeError: obj is undefined
return obj.nodeValue;

delete seems to be working OK update seems to be working fine, but still, name field remains empty.

can somebody please help me where can be the problem? thanks a lot!

by the way, it would be awesome to build this extension on top of giix!

#9611 report it
andrew1 at 2012/08/28 07:20pm
Combining with bootstrap extension

Brilliant extension!

Just thought I would add a note to help others resolve possible minor conflicts when using with the bootstrap extension.

Don't know why but I had to shift jquery to load at the top rather than the bottom in bootstrap.

Also needed to strip the registered css files out before the return from the ajax calls as the newly inserted css files were conflicting with the desired cascading order and mucking up the display. Could be just my app and the order things rendered in perhaps.

#7912 report it
Karasko at 2012/04/25 10:02pm

No critics, i appreciate your piece of work. And this isn't just a piece of code i took from you, this is published as an extension, i think you are also interested in quality of your code... just be sure using undefined variables always been evil not depending on whether it on production, or with any error_reporting level set. Took it is a advice pls. Cheers

#7893 report it
drumaddict at 2012/04/25 04:19am

You should be able to make all the changes to the code to serve your needs.Stop wining and don't expect that other's code will suit your needs out of the box.On production server nobody uses warnings in error reporting,it suits me.If you want it some other way,modify the code.Last advice,stop criticizing other's extensions when you have never developed a single one.Learn to appreciate and respect.

#7887 report it
Karasko at 2012/04/24 08:42pm
The installation includes bugfixes process )

Drumaddict At 2012/04/13 02: 48am @saegeek Try lowering your error reporting level to something less than strict whata bad advice

drumaddict, i'm interested in your extension. Unfortunately in setup process, i understood, that your error_level_repoting when you wrote it was so low, that i got not one error installing demo with my error_level_reporting=E_ALL (which consists also of E_NOTICE - that one very useful for DEVELOPMENT process, though may be security risky in PRODUCTION - as i know due to much info may revealed).

So if you plan to support this extension, i suggest that you should write it with E_NOTICE enabled... Not to mistake with E_STRICT - will not help in this case, definition of vars are checked by E_NOTICE

Anyway i'm sure your ext will help me to deal with jsTree obscure methods params. Thanks

#7732 report it
saegeek at 2012/04/13 02:34am

In the demo, when i click "Create Root" nothing happens and Firebug says : PHP Error 500: Undefined variable: updatesuccess (/var/www/protected/views/categorydemo/_form.php:55

#6440 report it
CNGOD at 2012/01/10 07:14pm
Remove after updatesuccess variables, but also in other mistakes. Please look below

Remove after updatesuccess variables, but also in other mistakes. Please look below

PHP Error [8]

Undefined index: name (D:\KuPan\wamp\www\mytree\protected\views\category\_form.php:122)

Could you put the web for the latest code issue: http://libkal.gr/yii_lab/categorydemo, thank you

#6423 report it
drumaddict at 2012/01/09 02:06pm

No big deal,this is a variable that was no longer needed and forgot to remove.Just delete it.If the error reporting is not STRICT,there will be no exception raised.

#6421 report it
CNGOD at 2012/01/09 10:10am
I found a mistake

PHP Error [8]

Undefined variable: updatesuccess (D:\KuPan\wamp\www\mytree\protected\views\category_form.php:54)

#5339 report it
drumaddict at 2011/10/05 03:49pm

I can only guess:You probably used a weird name for your model and the generator messed up,because the model name is used to name the ADMIN_TREE_CONTAINER_ID constant.Avoid names like MyModel,My-Model,My_Model,(and other characters separating My and Model).Try Mymodel. Again,it's only my guess.If the problem persists,mail me (from my profile).

UPDATE:It's the error reporting settimg in your php.ini,exclude warnings.

#5338 report it
Pokok at 2011/10/05 03:25pm

Hi drumaddict, thank you for your great work. I followed your instructions step by step but I get an error creating the crud (model generator works fine). Use of undefined constant php - assumed 'php' /WebRoot/myapplication/protected/gii/crud/templates/nested/index.php(181) Any solution? Thanks again

Leave a comment

Please to leave your comment.

Create extension