CTreeView AJAX Tree


(Macinville) #1

I have read this particular wiki and I want to use it as a sidebar navigation. However, I can’t see any option so as to make the last children as links.

Any idea on how I can achieve this?


(Macinville) #2

Hmmm…okay, I think I have found a way. I will share the codes once I have finalized it. :)


(Macinville) #3

Here’s my table:




CREATE TABLE `menu` (

 `id` int(11) NOT NULL AUTO_INCREMENT,

 `id_parent` int(11) DEFAULT NULL,

 `title` varchar(25) COLLATE utf8_unicode_ci NOT NULL,

 `position` int(2) NOT NULL,

 `url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,

 `icon` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,

 PRIMARY KEY (`id`),

 KEY `id_parent` (`id_parent`)

) ENGINE=InnoDB 



Here’s what I put in my controller:




	/**

	* Fills the JS tree on an AJAX request.

	* Should receive parent node ID in $_GET['root'],

	*  with 'source' when there is no parent.

	*/

	public function actionAjaxFillTree(){

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

			exit();

		}

		$parentId = "NULL";

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

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

		}

		$sql = "SELECT m1.id, m1.title AS text, m2.id IS NOT NULL AS hasChildren,m1.url "

		. "FROM menu AS m1 LEFT JOIN menu AS m2 ON m1.id=m2.id_parent "

		. "WHERE m1.id_parent <=> $parentId "

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

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

		$children = $req->queryAll();


		$children = $this->createLinks($children);


		echo str_replace(

			'"hasChildren":"0"',

			'"hasChildren":false',

			CTreeView::saveDataAsJson($children)

		);

		exit();

	}

	

	private function createLinks($children){

		$child = array();

		$return = array();

		foreach($children AS $key=>$value){

			$child['id']=$value['id'];

			$child['text']=$value['text'];

			$child['hasChildren']=$value['hasChildren'];

			

			if(strlen($value['url'])>0){

				$child['text'] = $this->format($value['text'],$value['url'],Yii::app()->request->url);

			}

				

			$return[] = $child;

			$child = array();

		}

		

		return $return;

	}

	

	private function format($text, $url,$icon = NULL)

	{

		$img = '';

		if(isset($icon))

			$img = '<img src="'.app()->theme->baseUrl.'/images/icons/'.$icon.'">';

		

		return sprintf('<span>%s</span>',CHtml::link(($img.' '.$text), app()->createUrl($url)));

	}



And here’s my view:




<?php

	$this->widget(

		'CTreeView',

		array(

			'animated'=>'fast', //quick animation

			'collapsed' => true,

			'url' => array('/backOffice/sideMenu/ajaxFillTree'),

			'htmlOptions'=>array(

				'class'=>'treeview-famfamfam',

			)

		)

	);

?>



As you might have noticed, it can put an image before the link if you have any.


(Talles D O P) #4

how can i configurate the view and the controler, could you make an example of how to create and link them , " sry im noob in yii =x "


(Macinville) #5

Hi talles,

Welcome to Yii :)

In case of the controller, all you have to do is paste it in your appropriate controller.

For example, put the controller codes I provided in /protected/controllers/SiteController.php, then the view codes in /protected/views/layouts/site/index.php (well this is not the right spot to put this kind of widget, but at least you would see how it works).

Don’t hesitate to experiment with Yii, and I suggest you read the this tutorial, or this blog-buiding tutorial to familiarize you more with Yii.

Happy Yii-ing!


(Talles D O P) #6

didnt worked =/ , i think that the error is here ‘url’ => array(’/backOffice/sideMenu/ajaxFillTree’),

i dont know what to put in these links


(Gmateos) #7

Hi,

I´ve also tried your implementation but nothing happens…

I´ve used your example as it is, the controller, the view, the table, everything.

is there any type of previous ajax setup that should be done before? Because the SimpleTree Yii extension is failing for me too.

Thanks in advance


(Macinville) #8

@talles

My tree controller is residing in BackOffice module. If you don’t have any any module containing the controller, just call it like ‘url’ => array(’/sideMenu/ajaxFillTree’), assuming that your controller is SideMenu.

@have3fun

Nope, no special setup whatsoever. Use firebug and enable the console so you can see the error in AJAX calls.


(Talles D O P) #9

my site/index

<h1>test</h1>

<?php

    &#036;this-&gt;widget(


            'CTreeView',


            array(


                    'animated'=&gt;'fast', //quick animation


                    'collapsed' =&gt; true,


                    'url' =&gt; array('site/ajaxFillTree'),


                    'htmlOptions'=&gt;array(


                            'class'=&gt;'treeview-famfamfam',


                    )


            )


    );

?>

my siteController

public function actionAjaxFillTree()

{


    if (&#33;Yii::app()-&gt;request-&gt;isAjaxRequest) {


        exit();


    }


    &#036;parentId = &quot;NULL&quot;;


    if (isset(&#036;_GET['root']) &amp;&amp; &#036;_GET['root'] &#33;== 'source') {


        &#036;parentId = (int) &#036;_GET['root'];


    }


    &#036;req = Yii::app()-&gt;db-&gt;createCommand(


        &quot;SELECT m1.id, m1.name AS text, m2.id IS NOT NULL AS hasChildren &quot;


        . &quot;FROM tree AS m1 LEFT JOIN tree AS m2 ON m1.id=m2.parent_id &quot;


        . &quot;WHERE m1.parent_id &lt;=&gt; &#036;parentId &quot;


        . &quot;GROUP BY m1.id ORDER BY m1.name ASC&quot;


    );


    &#036;children = &#036;req-&gt;queryAll();


    echo str_replace(


        '&quot;hasChildren&quot;:&quot;0&quot;',


        '&quot;hasChildren&quot;:false',


        CTreeView::saveDataAsJson(&#036;children)


    );


    exit();


}

my db:

– phpMyAdmin SQL Dump

– version 3.3.9

http://www.phpmyadmin.net

– Servidor: localhost

– Tempo de Geração: Mai 30, 2011 as 04:28

– Versão do Servidor: 5.5.8

– Versão do PHP: 5.3.5

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;

/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;

/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;

/*!40101 SET NAMES utf8 */;

– Banco de Dados: test


– Estrutura da tabela menu

CREATE TABLE IF NOT EXISTS menu (

id int(11) NOT NULL AUTO_INCREMENT,

id_parent int(11) DEFAULT NULL,

title varchar(25) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,

position int(2) NOT NULL,

url varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,

icon varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,

PRIMARY KEY (id),

KEY id_parent (id_parent)

) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

– Extraindo dados da tabela menu

i dont know why it doesnt works =/


(Gmateos) #10

Hi again, and thanks for your quick response.

I´ve checked firebug console but there´s no log related to AJAX calls.

I don´t know where is the problem, i´ve spent two days on this when it´s supposed to be quite simple, right?

This is the snippet in my SiteController:




 public function actionTree(){

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

                        exit();

                }

                $parentId = "NULL";

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

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

                }

                $sql = "SELECT m1.id, m1.title AS text, m2.id IS NOT NULL AS hasChildren,m1.url "

                . "FROM menu AS m1 LEFT JOIN menu AS m2 ON m1.id=m2.id_parent "

                . "WHERE m1.id_parent <=> $parentId "

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

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

                $children = $req->queryAll();


                $children = $this->createLinks($children);


                echo str_replace(

                        '"hasChildren":"0"',

                        '"hasChildren":false',

                        CTreeView::saveDataAsJson($children)

                );

                exit();

        }



And this is the code in my wiew:




<?php

        $this->widget(

                'CTreeView',

                array(

                        'animated'=>'fast', //quick animation

                        'collapsed' => true,

                        'url' => array('/site/tree'),

                )

        );	

?>



so that my test page is localhost/index.php/site/tree

Can you see where the problem is?

Thanks!


(Macinville) #11

Hi talles,

First of, enclose your code inside the code tags ([code ] and [\code ], without the spaces) so it can be viewed better.

There is something wrong with your query.

  • your table name is "menu", yet you are querying from the table "tree"

  • you don’t have a column “name”

Use firebug in firefox so you can see the error messages in every ajax calls (just enable the console). I guess you are mixing the wiki with my example. I suggest you follow the wiki first, so you will not be confused with my sample. My sample is how to make the tree leaves linkable, but it is important that you are able to create a tree first. :)


(Gmateos) #12

:o

It seems to exit in the very beginning:


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

                        exit();

}

That’s the problem. Do you know why is not an ajax request?

Thats whay i was wondering if I should do anything to enable Ajax or what…

I would appreciatte if you could give any hint on this. Thank u.


(Macinville) #13

Hi hav3fun,

Wierd, because I actually got it working.

These is my table:




CREATE TABLE `menu` (

 `id` int(11) NOT NULL AUTO_INCREMENT,

 `id_parent` int(11) DEFAULT NULL,

 `title` varchar(25) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,

 `position` int(2) NOT NULL,

 `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,

 `icon` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,

 PRIMARY KEY (`id`),

 KEY `id_parent` (`id_parent`)

) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1



This is the part of my controller:




public function actionAjaxFillTree() {

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

            exit();

        }

        $parentId = "NULL";

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

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

        }

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

                        "SELECT m1.id, m1.title AS text, m2.id IS NOT NULL AS hasChildren "

                        . "FROM menu AS m1 LEFT JOIN menu AS m2 ON m1.id=m2.id_parent "

                        . "WHERE m1.id_parent <=> $parentId "

                        . "GROUP BY m1.id ORDER BY m1.title ASC"

        );

        $children = $req->queryAll();

        echo str_replace(

                '"hasChildren":"0"', '"hasChildren":false', CTreeView::saveDataAsJson($children)

        );

        exit();

    }



And this is my view:




<?php

$this->widget('CTreeView', array(

    'animated' => 'fast', //quick animation

    'collapsed' => true,

    'url' => array('site/ajaxFillTree'),

    'htmlOptions' => array(

        'class' => 'treeview-famfamfam',

    ))

);

?>



insert these in your menu table for samples:




INSERT INTO `menu` (

`id` ,

`id_parent` ,

`title` ,

`position` ,

`url` ,

`icon`

)

VALUES (

'1', NULL , 'tree1', '', '', NULL

), (

'2', '1', 'subtree1', '', '', NULL

), (

'3', NULL , 'tree2', '', '', NULL

), (

'4', '3', 'subtree2', '', '', NULL

), (

'5', '3', 'subtree2', '', '', NULL

);





(Gmateos) #14

Thanks for the info,

Finally it worked yesterday. Basically I didn´t changed anything but in the way of calling the view with the tree, so that I´m sure that the call is an AJAX call.

Now I´m trying with the SimpleTree extension, which was my intention in the first place. Wish me luck! :)

Thanks


(Talles D O P) #15

YEAAAAH , IT WORKED , Thanks Macinville , you hellped me alot =D . :D


(Macinville) #16

@hav3fun

Glad you got it rolling. Good luck! :)

@talles

Welcome! Good luck also! :)


(Samarrizvi Lko) #17

Hi, I am having the same problem that have3fun was having. The html only shows


<ul class="treeview-famfamfam" id="yw0"></ul>

and no content is loaded. I am using the wiki example. Can you help, is there a problem with accessrules.


(Tzwang) #18

the problem that caused the sample code above not working is this

app()->createUrl

it missed Yii::app()->createUrl

after i changed that, it works.


(Ostovarit) #19

Hi

CTreeView won’t display when i add createLinks() function

my CTreeView works great with out urls

how can i add url for each nodes??


(Macinville) #20

I’m currently working on extending the CTreeView to allow links if is given in the table. But for now, can you please post your table here? Let me use it to check my extension if it will work.