MTreeView

MTreeView extends CTreeView, which displays a tree view of hierarchical data. It can handle both nested set and adjacency hierarchy model,and can create a linked node and adds icon if you wish. It can also be used to render AJAX tree!

Click here download the extension, and extract it to your extensions folder.

Here is an example on how to use it:




$this->widget('application.extensions.MTreeView.MTreeView',array(

	'collapsed'=>true,

	'animated'=>'fast',

	//---MTreeView options from here

	'table'=>'menu_adjacency',//what table the menu would come from

	'hierModel'=>'adjacency',//hierarchy model of the table

	'conditions'=>array('visible=:visible',array(':visible'=>1)),//other conditions if any                                    

	'fields'=>array(//declaration of fields

		'text'=>'title',//no `text` column, use `title` instead

		'alt'=>false,//skip using `alt` column

		'id_parent'=>'parent_id',//no `id_parent` column,use `parent_id` instead

		'task'=>false,//

		'icon'=>false,

		'url'=>false

	),

));



Download the sample MTreeView application so you can play with the extension. Comments and suggestions are very much welcome.

You can view my blog for a more detailed explanation.

Edit:

I have updated the extension to version 1.1, wherein nodes can have their individual ‘htmlOptions’. Visit my blog or the extensions page to download the latest zip files and to know the details of the updates.

Downloading now - looks promising!

Thanks waterloomatt! Please don’t hesitate to inform me of your observations, comments and suggestions. :)

Thanks macinville, you’ve done a great jopb.

I’m having a problem with the url property. Using AR I would format it:


CHtml::link(CHtml::encode($product->Name),array('view','id'=>$product->ProductId),$options)

So I set the text property to ‘Name’, but there isn’t a column in the database to return the url.

Is there a way to achieve this?

Hi Timbo,

Let me think of a way for you while on the way home.

Laters!

Some food for your thoughts: why not do it like some other zii widgets: use evaluation such as:


'url'=>array('view','id'=>'$data->ProductId')

In this way you’ll be able to specify expressions in other properties too.

Hi again,

Thanks Timbo! I was actually trying to do that along with my update yesterday, but I was not able to finish it apparently. Anyway, I’ll try to finish it as soon as possible. Please bear with me.

Edit:

Oh, btw…just in case anybody is able to accomplish this first, please share it to us so I can update the extension.

MTreeView has been updated to version 2:

  • added the option ‘encode’ (bool), which will CHtml::encode() the node if set to true

  • edited some codes

  • changed the template default to {icon} {text}" (added space in between)

  • removed the field ‘position’ as one of the selected field to avoid errors in query

  • fixed the indentation. Proper indentation is lost when file is opened in other editors such as Notepad++.

  • redeclared the static variables to its default values so as not to affect other MTreeView especially when rendered in a single page.

  • allowed declaring of array in url, just like that in Yii::app()->createUrl(). ‘url’ field can be declared in array in the format array(string $route,array $params). $params is in (‘field name’=>‘field that has the value’) format, like (‘id’=>‘id’).(NOTE: cannot be used in AJAX tree.)

Please test the new release if you have time.

Many thanks!

Download extension: MTreeView dowload section

Explanation: MTreeView details

Edit: updated the links

Thanks macinville - the url stuff works great.

Just one little error - in redeclaring the static template, you use the old version.

Thanks Timbo. I have updated the downloadable ZIP file to reflect your comment.

I am working on MTreeView so it can render ajaxLinks. Kindly inform me if there are any other features or bug fixes that I should include on my next update. Thanks!

MTreeView can now render AJAX-TreeView.

Click here for further details about the updates, or click here for the downloadable files.

thank’s i understand

Will this support drag and drop of nodes?

That would be lovely. :)

Hi Macinville,

I’m quite new to YII and started using MTreeView to display/manage a collection of folders and files.

My two models are properly built and relationed (giix did a great job…) and displaying them using MTree was a joke.

I have problems putting ajax links tough, hope you could advice.

In my tree-filling controller’s method I wrote:


	    

	public function actionXLSFolderFill(){

		Yii::import('application.extensions.MTreeView.MTreeView');

	    if (!Yii::app()->request->isAjaxRequest) {

		    exit();

	    }

            $parentId = "NULL";

            // default query select all folders

	    $sql = "SELECT m1.id, "

	    . "m1.name AS text, "

	    . "m2.id IS NOT NULL AS hasChildren, "

	    . "'#' AS url, "

	    . "'' AS icon, "

            . "m1.name AS tooltip, "

    	    . "'' AS options "

	    . "FROM yi3_xlsfolder AS m1 LEFT JOIN yi3_xlsfile AS m2 ON m1.id=m2.xlsfolder_id "

	    . "GROUP BY m1.id ORDER BY m1.name ASC";

	    if (isset($_GET['root']) && $_GET['root'] !== 'source') {

		// 'branch' query selects all files belonging to a specific folder

                $parentId = (int) $_GET['root'];

	        $sql = "SELECT m1.id, "

	    	. "m1.name AS text, "

	    	. "0 AS hasChildren, "

	    	. "'#' AS url, "

	    	. "'' AS icon, "

	    	. "m1.name AS tooltip, "

	    	. "'' AS options "

		    . "FROM yi3_xlsfile AS m1 "

		    . "WHERE m1.xlsfolder_id = $parentId "

		    . "GROUP BY m1.id ORDER BY m1.name ASC";

		    }

	    $req = Yii::app()->db->createCommand($sql);

	    $children = $req->queryAll();


            MTreeView::$_template_ =  "{icon} {text}";

	    MTreeView::$_assetsPath_ = Yii::app()->request->baseUrl.'/images/';

	    echo str_replace(

		    '"hasChildren":"0"',

		    '"hasChildren":false',

		    MTreeView::saveDataAsJson($children)

	    );

	    exit();

         }

}



Then, in my view, I have:


<?php

	$this->widget('application.extensions.MTreeView.MTreeView',

	array('url'=>array('XLSFolderFill'),

		'animated'=>'fast',

		'persist'=>'cookie',

		'htmlOptions'=>array(

			'class'=>'treeview-famfamfam',

			),

                // <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/huh.gif' class='bbc_emoticon' alt='???' />?<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/huh.gif' class='bbc_emoticon' alt='???' />

		'template'=>'{icon}&nbsp;{text}',

		'ajaxOptions'=>array('update'=>'#XLSDetails')

		)

	);

?>

</div>


<div id="XLSDetails"> </div>

Like this, eveything works as expectd. Now, I would like to populate the XLSDetails div with folder or file data, depending on which tree node was clicked, with data taken from respective ‘_view’ partials.

Not to mention populating target div with data from two different models, I couldn’t find a working way to populate the div at all!

I’ve tried adding a ‘fields’ array (as per the example) but it didn’t work.

I’ve tried adding code to my controller’s method (as per http://www.yiiframework.com/wiki/215/adding-class-and-links-to-ctreeview-node/) but it didn’t work either.

What would you (or anybody else with more experience than me) suggest?

Thanks for your great extension (it did teach me different things!).

Cheers,

rash*

Me again,

I managed to build url into nodes (I do this inside my controller) and they do work, so a folder node gets a url like:


xlsfolder/view&id=2



while files get:


xlsfile/view&id=3



I’ve also monitored ajax calls/responses with firebug and everything works fine.

Then I tried to implement another solution (again by you, http://www.yiiframework.com/forum/index.php?/topic/19253-ctreeview-ajax-tree/page__view__findpost__p__94249) but as soon as I call createLinks my tree goes blank and firebug shows no more ajax stuff; this happens at root (source) level, right away.

How do I turn my links into ajax calls?

Cheers,

rash*

Ok, I pay for being a newbie here…

After a lot of searching and reading and browsing code, I’ve realized MTree is oversized and not tailored to my needs.

Still, it’s been interesting because looking at the code made me find the right way, I believe.

What I need is to ‘downgrade’ my tree to CTreeView and build links within my controller: to this, MTree code is more than inspiring!

So thank you Macinville, I took lesson one!

Cheers

rash*

Hi rashmani,

So sorry I have been busy with my personal projects (not Yii-related) that I was not even able to check my email or update my blog for the past few months. Anyway, I’m glad that MTreeView has somehow helped you. So glad to be of help. :)

If item text appears a little messed up when using icons, include the following CSS code inline or in a .css file:

.treeview li img {

vertical-align:text-top;

}

Took quite a while to figure that out! Please also post this message on the extension page - it appears I am too new to post there.

Fiddling around with Yii 1.1.10 and MTreeView 2.1, I ran into a problem where the Yii debugger (thanks for that!) kept telling me there was either an array-to-string error, or an unknown array item, in CUrlManager. After some digging and a lot of experimentation, I figured out what I think is the cause.

If you use the URL option in the MTreeView widget like so:


$this->widget('application.extensions.MTreeView.MTreeView', array(

        'fields'=>array(

            'url'=>array('activity/view',array('id'=>'id')),

            ...

        ),

        ...

    )

);



then MTreeView.php’s createUrl function tries to assemble this into a comprehensible URL, but fails. The final line in this function (line 291) says


return Yii::app()->createUrl($this->_url[0], $arrTemp, $arrOptions);

but CUrlManager expects the third argument to be the URL option delimiter (usually an ampersand, cf. ../yii/framework/web/CUrlManager.php, line 280). By changing the above MTreeView line of code to


return Yii::app()->createUrl($this->_url[0], array_merge($arrTemp,$arrOptions));

I finally got it to work.

In case I totally missed the point here, I am more than willing to be taught. If not, I hope it may benefit others.