creocoder / yii2-nested-sets

The nested sets behavior for the Yii framework.
Other
446 stars 129 forks source link

Widget #59

Open nepster-web opened 9 years ago

nepster-web commented 9 years ago

Здравствуйте. Было бы здорово, если бы вы добавили старый пример в доки:

$categories = Category::find()->addOrderBy('lft')->all();
$level = 0;

foreach ($categories as $n => $category)
{
    if ($category->level == $level) {
        echo Html::endTag('li') . "\n";
    } elseif ($category->level > $level) {
        echo Html::beginTag('ul') . "\n";
    } else {
        echo Html::endTag('li') . "\n";

        for ($i = $level - $category->level; $i; $i--) {
            echo Html::endTag('ul') . "\n";
            echo Html::endTag('li') . "\n";
        }
    }

    echo Html::beginTag('li');
    echo Html::encode($category->title);
    $level = $category->level;
}

for ($i = $level; $i; $i--) {
    echo Html::endTag('li') . "\n";
    echo Html::endTag('ul') . "\n";
}
creocoder commented 9 years ago

Дело в том, что для этого планируется отдельный виджет. Поэтому я не думаю, что в документации есть смысл показывать столь сложный код :)

brussens commented 9 years ago

Виджет? Интересно. А когда планируется его появление, если не секрет? P.S.: Спасибо за поведение :)

creocoder commented 9 years ago

@brussens Планируется к релизу, который довольно скоро.

brussens commented 9 years ago

@creocoder спасибо за инфо :) Будем ждать :)

ostashevdv commented 9 years ago

Стоит ли продолжать ждать виджета? Можно ли будет с помощью виджета перемащать, создавать ноды?

arogachev commented 9 years ago

I'm also interested in this widget. Could you provide more information about its features and release date?

creocoder commented 9 years ago

@arogachev Widget is not main direction of such extension, so i'm still thinking about features.

rubenheymans commented 9 years ago

how can I create an array for the navbar widget?
this is the output I need

Array
(
    [0] => Array
        (
            [label] => Home
            [url] => ''
            [active] => 1
        )

    [1] => Array
        (
            [label] => Contact
            [url] => ''
            [active] => 
            [items] => Array
            (
                [0] => Array
                    (
                        [label] => Over ons
                        [url] => ''
                        [active] => 
                    )

                [1] => Array
                    (
                        [label] => Video
                        [url] => ''
                        [active] => 
                    )
            )
        )
    [2] => Array
        (
            [label] => White Light
            [url] => ''
            [active] => 
        )
    [3] => Array
        (
            [label] => Support
            [url] => ''
            [active] => 
        )
    [4] => Array
        (
            [label] => Downloads
            [url] => ''
            [active] => 
        )
)
arogachev commented 9 years ago

Seems like @creocoder is busy now.

I actually wrote widget based on JsTree for managing Nested Sets structure.

I found couple of existing solutions but was not satisfied with GUI and some functionality.

For those who are interested - https://github.com/arogachev/yii2-tree.

It's pretty raw, but working and better than nothing.

Any advices / improvement tips / issues are welcomed.

@rubenheymans I have separate behavior in this extension for building hierarchical array. We can slightly modify it to provide the output you mentioned and even include custom NavBar for that.

But as far as I remember with NavBar the nesting is limited by 2 levels (in Bootstrap 3).

There is no README currently, but I will write it soon.

rubenheymans commented 9 years ago

This is a start, but it's only 2 levels deep (which is ok for bootstrap menu's)

Generate the array:

 public static function getMenuTree($settings = ['root' => null, 'level' => 1, 'includeLanguage' => true])
    {
        $items = [];

        // Load the provided root category and check if it exists
        $rootCategory = Category::findOne($settings['root']);

        if (!$rootCategory) {
            throw new Exception(Yii::t('app', 'Root category does not exist'));
        }

        // Load categories
        $categories = Category::find()->where(['root' => $rootCategory->id, 'level' => $settings['level']])->addOrderBy('lft')->all();

        // Add the categories to the html output
        foreach ($categories as $k => $category) {

            $url = $category->getUrl($settings['includeLanguage']);

            $item = [
                'label'     => $category->name,
                'url'       => $url,
                'active'    => Yii::$app->request->url == $url,
            ];

            // Get the item's children
            $children = $category->descendants()->all();

            if ($children) {
                $item['items'] = [];

                foreach ($children as $k => $child) {
                    $url = $child->getUrl($settings['includeLanguage']);

                    $item['items'][] = [
                        'label'     => $child->name,
                        'url'       => $url,
                        'active'    => Yii::$app->request->url == $url,
                    ];
                }
            }

            // Add new item to items array
            $items[] = $item;
        }

        return $items;
    }

getUrl function:

public function getUrl($includeLanguage = true)
    {
        $prefix = ($includeLanguage) ? "{$this->language}/" : '';

        return Url::to("{$prefix}{$this->alias}");
    }

Navbar widget:

<?php

$categories = Category::getMenuTree(['level' => 1, 'root' => 1, 'includeLanguage' => (Yii::$app->language == 'nl') ? false : true]);

    NavBar::begin([
        'brandLabel' => Html::img('@web/frontend/web/img/logo.jpg', ['class' => 'img-responsive logo']),
        'brandUrl' => Yii::$app->homeUrl,
        'options' => [
            'class' => 'navbar navbar-inverse',
        ],
    ]);

    echo Nav::widget([
        'options' => ['class' => 'navbar-nav'],
        'items' => ($categories) ? $categories : [],
        'activateItems' => true,
        'activateParents' => true
    ]);

    NavBar::end();
?>
arogachev commented 9 years ago

@rubenheymans Did you check this behavior? Your implementation is tightly connected with your model structure and needs.

nepster-web commented 9 years ago

Еще момент. Там в вешепредставленнном коде есть ошибки с семантикой списков. Как раз работаю сейчас со тсруктурами, вот хороший пример:

        foreach ($users as $n => $user)
        {
            if (!$user->depth) {
                echo Html::beginTag('ul') . PHP_EOL;
            }

            if ($user->depth && $user->depth == $level) {
                echo Html::endTag('li') . PHP_EOL;
            } elseif ($user->depth > $level) {
                echo PHP_EOL . Html::beginTag('ul') . PHP_EOL;
            } else {
                if ($user->depth) {
                    echo Html::endTag('li' . $user->depth) . PHP_EOL;
                }
                for ($i = $level - $user->depth; $i; $i--) {
                    echo Html::endTag('ul') . PHP_EOL;
                    echo Html::endTag('li') . PHP_EOL;
                }
            }

            echo Html::beginTag('li');
            echo Html::encode($user->user->username);
            $level = $user->depth;
        }

        for ($i = $level; $i; $i--) {
            echo Html::endTag('li') . PHP_EOL;
            echo Html::endTag('ul') . PHP_EOL;
        }