简体   繁体   中英

Sortable behavior in admin listing in Sonata Admin

I have a list of categories that I would like to sort (change the order). I use Sonata Admin for my backend. I've tried to provide this with the following tutorial .

This is my Category Entity :

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation\SortablePosition;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * Category
 *
 * @ORM\Table(name="category", indexes={@ORM\Index(name="fk_category_category_idx", columns={"parent_category_id"})})
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CategoryRepository")
 */
class Category
{
    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @var boolean
     *
     * @ORM\Column(name="enabled", type="boolean", nullable=false)
     */
    private $enabled = true;

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var \AppBundle\Entity\Category
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="parent_category_id", referencedColumnName="id")
     * })
     */
    private $parentCategory;

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

    public function __toString()
    {
        //return $this->getName();
        if($this->getParentCategory()){
            return '(' . $this->getParentCategory()->getName() . ')' . ' ' . $this->getName();
        }
        else{
            return $this->getName();
        }
    }

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Category
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set enabled
     *
     * @param boolean $enabled
     *
     * @return Category
     */
    public function setEnabled($enabled)
    {
        $this->enabled = $enabled;

        return $this;
    }

    /**
     * Get enabled
     *
     * @return boolean
     */
    public function getEnabled()
    {
        return $this->enabled;
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set parentCategory
     *
     * @param \AppBundle\Entity\Category $parentCategory
     *
     * @return Category
     */
    public function setParentCategory(\AppBundle\Entity\Category $parentCategory = null)
    {
        $this->parentCategory = $parentCategory;

        return $this;
    }

    /**
     * Get parentCategory
     *
     * @return \AppBundle\Entity\Category
     */
    public function getParentCategory()
    {
        return $this->parentCategory;
    }

    /**
     * Set position
     *
     * @param integer $position
     *
     * @return Category
     */
    public function setPosition($position)
    {
        $this->position = $position;

        return $this;
    }

    /**
     * Get position
     *
     * @return integer
     */
    public function getPosition()
    {
        return $this->position;
    }
}

As you can see I have a property $position and also a getter and setter for it.

In services.yml I have:

services:
    gedmo.listener.sortable:
        class: Gedmo\Sortable\SortableListener
        tags:
            - { name: doctrine.event_subscriber, connection: default }
        calls:
            - [ setAnnotationReader, [ "@annotation_reader" ] ]

And:

admin.category:
    class: AppBundle\Admin\CategoryAdmin
    arguments: [~, AppBundle\Entity\Category, 'PixSortableBehaviorBundle:SortableAdmin']
    tags:
        - { name: sonata.admin, manager_type: orm, label: Categorieën }
    calls:
        - [ setPositionService, ["@pix_sortable_behavior.position"]]

In my config.yml I have:

stof_doctrine_extensions:
    orm:
        default:
            sortable: true

And in my CategoryAdmin I have:

<?php

namespace AppBundle\Admin;

use AppBundle\Entity\Category;
use AppBundle\Repository\CategoryRepository;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;

class CategoryAdmin extends AbstractAdmin
{
    public $last_position = 0;

    private $positionService;

    protected $datagridValues = array(
        '_page' => 1,
        '_sort_order' => 'ASC',
        '_sort_by' => 'position',
    );

    public function setPositionService(\Pix\SortableBehaviorBundle\Services\PositionHandler $positionHandler)
    {
        $this->positionService = $positionHandler;
    }

    protected function configureFormFields(FormMapper $formMapper)
    {
        $entity = new Category();
        $query = $this->modelManager->getEntityManager($entity)->createQuery('SELECT c FROM AppBundle\Entity\Category c WHERE c.parentCategory IS NULL');

        $formMapper
            ->add('name', 'text', array('label' => 'Naam'))
            ->add('parentCategory', 'sonata_type_model', array('label' => 'Hoofdcategorie', 'required' => false, 'query' => $query, 'multiple' => false, 'btn_add' => false))
            ->add('enabled', 'checkbox', array('label' => 'Actief', 'required' => false));
    }

    protected function configureDatagridFilters(DatagridMapper $datagridMapper)
    {
        $datagridMapper->add('name');
    }

    protected function configureRoutes(RouteCollection $collection)
    {
        $collection->add('move', $this->getRouterIdParameter().'/move/{position}');
    }

    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper
            ->addIdentifier('name', null, array('label' => 'Naam'))
            ->add('enabled', null, array('label' => 'Actief'))
            ->add('parentCategory', null, array('label' => 'Hoofdcategorie'))
            ->add('_action', null, array(
                    'actions' => array(
                        'move' => array(
                            'template' => 'AppBundle:Sonata:_sort.html.twig'
                        ),
                    )
                )
            );
        //;
    }
}

In the view _sort.html.twig I have:

{% if admin.isGranted('EDIT', object) and admin.hasRoute('edit') %}
    {% set pix_position = sortableObjectPosition(object) %}

    {% if pix_position < admin.last_position %}
        <a class="btn btn-sm btn-default" href="{{ admin.generateObjectUrl('move', object, {'position': 'bottom'}) }}" title="{{ 'move_to_bottom'|trans }}">
            {{- 'icon_move_to_bottom'|trans -}}
        </a>
    {% endif %}

    {% if pix_position < admin.last_position %}
        <a class="btn btn-sm btn-default" href="{{ admin.generateObjectUrl('move', object, {'position': 'down'}) }}" title="{{ 'move_down'|trans }}">
            {{- 'icon_move_down'|trans -}}
        </a>
    {% endif %}

    {% if pix_position > 0 %}
        <a class="btn btn-sm btn-default" href="{{ admin.generateObjectUrl('move', object, {'position': 'up'}) }}" title="{{ 'move_up'|trans }}">
            {{- 'icon_move_up'|trans -}}
        </a>
    {% endif %}

    {% if pix_position > 0 %}
        <a class="btn btn-sm btn-default" href="{{ admin.generateObjectUrl('move', object, {'position': 'top'}) }}" title="{{ 'move_to_top'|trans }}">
            {{- 'icon_move_to_top'|trans -}}
        </a>
    {% endif %}
{% endif %}

I'm not getting any errors. But there are no buttons shown in my "Actions" column. The HTML is like this:

<td class="sonata-ba-list-field sonata-ba-list-field-text" objectid="28">
    <div class="btn-group">
    </div>
</td>

When I dump the variable pix_position from my twig file I get 0 . When I dump the variable admin.last_position I also get 0 . In my database all the position fields are 0. But how can I order them in my backend than?

UPDATE 2:

Now the buttons are shown.

在此处输入图片说明

But when I click on the left one he places it on top, and not one up. Same for the button on the right... . When I click on the left button he should only go one place up.

{% if admin.isGranted('EDIT', object) and admin.hasRoute('edit') %}
    {% set pix_position = sortableObjectPosition(object) %}

    {% if pix_position < admin.last_position %} // Won't pass
        <a class="btn btn-sm btn-default" href="{{ admin.generateObjectUrl('move', object, {'position': 'bottom'}) }}" title="{{ 'move_to_bottom'|trans }}">
            {{- 'icon_move_to_bottom'|trans -}}
        </a>
    {% endif %}

    {% if pix_position < admin.last_position %} // Won't pass
        <a class="btn btn-sm btn-default" href="{{ admin.generateObjectUrl('move', object, {'position': 'down'}) }}" title="{{ 'move_down'|trans }}">
            {{- 'icon_move_down'|trans -}}
        </a>
    {% endif %}

    {% if pix_position > 0 %} // Won't pass, but 1 yes
        <a class="btn btn-sm btn-default" href="{{ admin.generateObjectUrl('move', object, {'position': 'up'}) }}" title="{{ 'move_up'|trans }}">
            {{- 'icon_move_up'|trans -}}
        </a>
    {% endif %}

    {% if pix_position > 0 %} // Won't pass, but 1 yes
        <a class="btn btn-sm btn-default" href="{{ admin.generateObjectUrl('move', object, {'position': 'top'}) }}" title="{{ 'move_to_top'|trans }}">
            {{- 'icon_move_to_top'|trans -}}
        </a>
    {% endif %}
{% endif %}

So, instead of init the default value to 0, just init it to 1

Update

Actually, if you move one object, it will go on top, because its value is 2 and all other are to 1.

One possibility, is instead of setting every thing to 1, is to set an incremential value by default.

Extract from this answer :

mysql_query("
    UPDATE member_profile 
    SET points = points + 1
    WHERE user_id = '".$userid."'
");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM