contributte/datagrid – tree view pomocí pole

MikKuba
Člen | 76
+
0
-

Ahoj,

Snažím se pomocí datagridu udělat tree view.
Jedná se mi o strukturu tabulky typu

id 	parent_id	name		priority
1	null		Jedna		1
2	1			Dvojka		2
3	null		Trojka		3
4	2			Čtyřka		4

Používám Doctrine a dotaz na join se mi nepodařilo napsat funkčně. Problém mi dělalo joinovat tak jak je v dokumentaci, ale pomocí dibi.

Rozhodl jsem se to použít jako klasické PHP pole. Napsal jsem si vlastní třídu na vytvoření toho stromu. Takto se to volá v gridu:

$grid->setDataSource($this->getTree($this->facade->getData([], "priority"))); // vytáhnu si data seřazená podle priority
$grid->setTreeView([$this, 'getChildren'], 'has_children');

// ....

public function getChildren($parentId): array
	{
		return $this->getResourcesTree($this->facade->getData([], "priority"), null, $parentId);
	}

A metoda, která zpracovává tree, případně pro navrácení jen toho „children“ uzlu s případnými dalšími uzly:

	private function getResourcesTree(array $resources, $parentId = null, $fromParent = null): array
    {
        $return = [];
        foreach ($resources as $resource) {
            if ($resource['parentId'] == $parentId) {
                $children = $this->getResourcesTree($resources, $resource['id']);
                if($children)
                    $resource['children'] = $children;
                $resource['has_children'] = isset($resource['children']) ? count($resource['children']) : 0;

                $return[$resource['id']] = $resource;
            }
        }
        if($fromParent){
            $return = $this->getChildrenTree($return, (int)$fromParent);
        }

        return $return;
    }

    private function getChildrenTree(array $resources, int $fromParent, $firstLoop = true): array
    {
        foreach($resources as $value){
            if($value['id'] == $fromParent){
                return $value['children'];
            }
            if(!$firstLoop && $value['parentId'] == $fromParent){
                if(isset($value['children'])){
                    return $value['children'];
                }
                else{
                    return $value;
                }
            }
            if(($value['has_children'] > 0) && !empty($value['children'])){
                $children = $this->getChildrenTree($value['children'], $fromParent, false);
                if($children){
                    return $children;
                }
            }
        }


        return [];
    }

Strom mi to vykreslí v základu správně, ty co mají potomky vidím správně možnost rozbalit. Když rozbalím takto první úroveň (ze základního stromu), funguje to. Jakmile je tam ale další vnořená položka, vidím správně šipku pro rozbalení. Ale po kliknutí na ní se mi celý grid resetuje. Dojde k redirectu, v consoli vidím StatusCode : 302 Found.

Když ale takto položku rozbalím, sbalím a zase rozbalím, tak se mi tam místo 1× zobrazí 3× ta stejná. Každou takovou další iterací (zavřít/otevřít) přibudou nové 2 položky duplicitně. A vždy ta první, jakmile tam je nějaká duplicitně, funguje a lze jí tedy rozbalit potomka, co předtím nešel.

Předem díky za jakékoliv rady, lámu si s tím hlavu už pár hodin.