Подготовка вариантов обновления иерархических категорий с помощью Дерева расширения Doctrine

Я использую дерево расширений Doctrine для управления категориями в иерархический способ в проекте Symfony.

Тем не менее, я не нашел, как просто управлять частью добавления/редактирования в twig: я могу отображать древовидную структуру html с помощью метода childrenHierarchy(), но я хотел бы пойти дальше и получить что-то вроде этого:

Root
- Cat 1  (+)
-- Cat 1-1  (+)
-- Cat 1-2  (+)
- Cat 2  (+)

Кнопка (+) открывает модальное окно, отображающее текстовое поле (категория), что позволяет разветвить этот элемент на выбранном родительском элементе.

Я не видел в документе (и я не вижу, если это возможно) использование этого метода childrenHierarchy() с параметрами, позволяющими использовать дополнительный HTML, с вызовом ajax.

Моя сущность является базовой:

<?php
namespace CPASimUSante\SimupollBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Claroline\CoreBundle\Entity\User;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * Simupoll categories
 *
 * @ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\NestedTreeRepository")
 * @ORM\Table(
 *      name="cpasimusante__simupoll_category",
 *      uniqueConstraints={
 *          @ORM\UniqueConstraint(name="category_unique_name_and_user", columns={"user_id", "name"})
 *      }
 * )
 * @DoctrineAssert\UniqueEntity({"name", "user"})
 * @Gedmo\Tree(type="nested")
 */
class Category
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * name of the category
     * @var string $value
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @Gedmo\TreeLeft
     * @ORM\Column(name="lft", type="integer")
     */
    private $lft;

    /**
     * @Gedmo\TreeLevel
     * @ORM\Column(name="lvl", type="integer")
     */
    private $lvl;

    /**
     * @Gedmo\TreeRight
     * @ORM\Column(name="rgt", type="integer")
     */
    private $rgt;

    /**
     * @Gedmo\TreeRoot
     * @ORM\Column(name="root", type="integer", nullable=true)
     */
    private $root;

    /**
     * @Gedmo\TreeParent
     * @ORM\ManyToOne(
     *     targetEntity="CPASimUSante\SimupollBundle\Entity\Category",
     *     inversedBy="children"
     * )
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $parent;

    /**
     * @ORM\ManyToOne(targetEntity="Claroline\CoreBundle\Entity\User")
     */
    private $user;

    /**
     * @ORM\OneToMany(
     *     targetEntity="CPASimUSante\SimupollBundle\Entity\Category",
     *     mappedBy="parent",
     * )
     * @ORM\OrderBy({"lft" = "ASC"})
     */
    protected $children;

    /**
     * propoerty used in hierarchy display, like selectbox
     */
    private $indentedName;

    public function __construct()
    {
        $this->children = new ArrayCollection();
    }

    /**
     * Returns the resource id.
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Sets the resource id.
     * Required by the ResourceController when it creates a fictionnal root
     *
     * @param integer $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Returns the children resource instances.
     *
     * @return \Doctrine\Common\ArrayCollection|Category[]
     */
    public function getChildren()
    {
        return $this->children;
    }

    /**
     * Returns the parent category.
     *
     * @return \CPASimUSante\SimupollBundle\Entity\Category
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Sets the parent category.
     *
     * @param \CPASimUSante\SimupollBundle\Entity\Category $parent
     */
    public function setParent(\CPASimUSante\SimupollBundle\Entity\Category $parent = null)
    {
        $this->parent = $parent;
    }

    /**
     * Return the lvl value of the resource in the tree.
     *
     * @return integer
     */
    public function getLvl()
    {
        return $this->lvl;
    }

    public function getUser()
    {
        return $this->user;
    }

    public function setUser(User $user)
    {
        $this->user = $user;
    }

    /**
     * allows hierachy display
     * @return string
     */
    public function __toString()
    {
        return $this->getName();
    }

    /**
     * allows hierachy display
     * @return string
     */
    public function getIndentedName()
    {
        return str_repeat("--", $this->lvl) . $this->name;
        //return str_repeat($this->getParent()." > ", $this->lvl) . $this->name;
    }
}

Мой контроллер на данный момент также является базовым, и здесь я думаю, что потенциально могу настроить параметры:

    public function indexAction(Simupoll $simupoll)
    {
        $em = $this->getDoctrine()->getManager();
        $user = $this->container
            ->get('security.token_storage')
            ->getToken()->getUser();
        $repo = $em->getRepository('CPASimUSanteSimupollBundle:Category');
        $options = array(
            'decorate' => true,
            'rootOpen' => '<ul>',
            'rootClose' => '</ul>',
            'childOpen' => '<li>',
            'childClose' => '</li>'
        );
        $htmlTree = $repo->childrenHierarchy(
            null, /* starting from root nodes */
            false, /* true: load all children, false: only direct */
            $options
        );
        return array(
            '_resource' => $simupoll,
            'tree' => $htmlTree,
        );
    }

Шаблон:

{% block section_content %}
    <div class="panel panel-default">
        <div class="panel-body" id="text_content">
            {{ tree |raw }}
        </div>
    </div>
{% endblock %}

Заранее спасибо, если у кого-то есть предложение или руководство.


person Overdose    schedule 27.01.2016    source источник


Ответы (1)


На самом деле именно опция nodeDecorator позволяла настроить вывод:

$options = array(
    'decorate' => true,
    'rootOpen' => '<ul>',
    'rootClose' => '</ul>',
    'childOpen' => '<li>',
    'childClose' => '</li>',
    'nodeDecorator' => function($node) {
        return $node['name']. '<a href="#" data-id="'.$node['id'].'" class="btn btn-primary category-add-btn">+</a>';
    }
);

а затем я мог бы использовать некоторые js в шаблоне ветки для отображения модального окна.

$('#treecontainer').on('click', '.category-add-btn', function(){
    //logic to display modal and pass parameter
});
person Overdose    schedule 28.01.2016