Symfony 1.4 Drag&Drop Nested Set Editor for Admin Generator
2012-08-24 21:35
459 查看
Most of my web application have some kind of hierarchical structure in their models. It gives my users the ability to categorize their data in a pleasant way. The only problem is that its hard to create a user interface for editing these hierarchies. I made a prototype which adds nested set support to the symfony (1.2) generator. This extension allows for full drag&drop nested set support! See for yourself by clicking the image:
click for a real demo of the nested set editor
The editor uses the
If you want to join the development or extend it, please send me an email or leave a reply to this entry.
One first note is that the current implementation of NestedSet has a bug. Moving a deep branch to the root may corrupt the tree. I made a ticket and patch, but it’s not yet patched in the repositories. So manually update your Doctrine library, or only use this code for testing purposes…
The editor is based on a really simple model, using Doctrine’s actAs NestedSet (see
Next step is creating a default admin generator for the ‘Tree’ model. How to do this is clearly explained in Jobeet day 12: the Admin Generator. I think I did something like:
Download the treeTable code, I copied the
I happen to like the way jQuery can be loaded through the googleapi system. Symfony can handle the full URL’s by default, this style is easy to maintain and upgrade. Google also makes sure the headers of the js library are set correctly, which minimizes reloads of the files.
TreeTable is then enabled by overwriting the
Doing this should give you a collapsible tree right inside your Admin Generator table.
For this I added a hidden select on each row of the table:
To clarify a little I added the screenshot below, in which the input element is still shown. After dropping the javascript seeks the id of the parent dropped on and types it into the input of the dragged item. Sending this to the server will enable the server to update the parent of the item. The code resides in the ‘executeBatchOrder’ function in
Add a
Make it possible to edit the order of children from the same parent (now it always inserts asFirstChild). Possible solution could be an interface like
Move the
Change this prototype into a Plugin
Thanks for reading!
From: http://redotheoffice.com/?tag=doctrine-drag-drop-admin-generator-symfony-nestedset
Other: http://halestock.wordpress.com/2010/02/03/symfony-implementing-a-nested-set-part-one/
http://symfonyguide.wordpress.com/2009/10/29/quick-doctrine-nestedset-reference/
click for a real demo of the nested set editor
The editor uses the
treeTablejQuery plugin with added D&D support.
Full source is available
Today I created theredotheofficegithub repository. Right there you can find the full source of the project.
If you want to join the development or extend it, please send me an email or leave a reply to this entry.
Explanation
As I’m quite short on time right now, so I’ll only do a brief explanation and give you hints where to look in the source.One first note is that the current implementation of NestedSet has a bug. Moving a deep branch to the root may corrupt the tree. I made a ticket and patch, but it’s not yet patched in the repositories. So manually update your Doctrine library, or only use this code for testing purposes…
The editor is based on a really simple model, using Doctrine’s actAs NestedSet (see
config/doctrine/nested.yml):
--- Tree: actAs: NestedSet: hasManyRoots: true rootColumnName: root_id columns: name: type: string(255)
Next step is creating a default admin generator for the ‘Tree’ model. How to do this is clearly explained in Jobeet day 12: the Admin Generator. I think I did something like:
./symfony generate:app backend ./symfony doctrine:generate-admin backend Tree --module=tree
jQuery treeTable plugin
First enhancement is to implement thetreeTableplugin. This turns the normal generated table into a collapsible tree.
Download the treeTable code, I copied the
.jsand
.cssto the
web/jsand
web/cssand added them to the
apps/backend/config/view.yml. Also make sure to load
jQuery:
default: http_metas: content-type: text/html metas: ~ stylesheets: - jQuery.treeTable.css - main.css javascripts: - http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js - http://ajax.googleapis.com/ajax/libs/jqueryui/1.5.3/jquery-ui.min.js - jquery.treeTable.js
I happen to like the way jQuery can be loaded through the googleapi system. Symfony can handle the full URL’s by default, this style is easy to maintain and upgrade. Google also makes sure the headers of the js library are set correctly, which minimizes reloads of the files.
TreeTable is then enabled by overwriting the
apps/backend/modules/tree/templates/_list.phptemplate with some code that writes the correct classes to the individual rows. Also the table needs an
idfor easy finding the object:
... <table id="main_list" cellspacing="0"> ... <tbody> <?php foreach ($pager->getResults() as $i => $tree): $odd = fmod(++$i, 2) ? 'odd' : 'even' ?> <tr id="node-<?php echo $tree['id'] ?>" class="sf_admin_row <?php echo $odd ?><?php // insert hierarchical info $node = $tree->getNode(); if ($node->isValidNode() && $node->hasParent()) { echo " child-of-node-".$node->getParent()->getId(); } ?>"> <?php include_partial('tree/list_td_batch_actions', array('tree' => $tree, 'helper' => $helper)) ?> <?php include_partial('tree/list_td_tabular', array('tree' => $tree)) ?> <?php include_partial('tree/list_td_actions', array('tree' => $tree, 'helper' => $helper)) ?> </tr> <?php endforeach; ?> </tbody> ... <script type="text/javascript"> function checkAll() { var boxes = document.getElementsByTagName('input'); for(index in boxes) { box = boxes[index]; if (box.type == 'checkbox' && box.className == 'sf_admin_batch_checkbox') box.checked = document.getElementById('sf_admin_list_batch_checkbox').checked } return true; } $(document).ready(function() { $("#main_list").treeTable({ treeColumn: 2, initialState: 'expanded' }); } </script>
Doing this should give you a collapsible tree right inside your Admin Generator table.
Adding Drag&Drop support
Adding drag & drop on the client side is done by adding some javascript to the end of the_list.phptemplate, see github. After dropping the item on a new parent the
treeTableplugin takes care of updating the client visual interface. It’s up to us to send the data back to the server.
For this I added a hidden select on each row of the table:
<td> <input type="checkbox" name="ids[]" value="<?php echo $tree->getPrimaryKey() ?>" class="sf_admin_batch_checkbox" /> <input type="hidden" id="select_node-<?php echo $tree->getPrimaryKey() ?>" name="newparent[<?php echo $tree->getPrimaryKey() ?>]" /> </td>
To clarify a little I added the screenshot below, in which the input element is still shown. After dropping the javascript seeks the id of the parent dropped on and types it into the input of the dragged item. Sending this to the server will enable the server to update the parent of the item. The code resides in the ‘executeBatchOrder’ function in
apps/backen/modules/tree/actions/actions.class.php.
TreeForm implementation
The implementation of the TreeForm is also noteworthy. It removes all nested set columns (root_id,
lft,
rgtand
level) and adds a fully functional dropdown for selecting the parent. This code can easily be dropped into your project and doesn’t depend on jQuery or any other external library. After submitting the form makes sure all columns for the nested set are properly updated to the new parent. See the image below, and the
TreeForm.class.phpfile at github.
Further enhancements
Things can always become better:Add a
serializefunction to treeTable which enables the possibility to get rid of the hidden input element on each row.
Make it possible to edit the order of children from the same parent (now it always inserts asFirstChild). Possible solution could be an interface like
nestedSortable
Move the
Update tree orderbatch action from the dropdown to the table footer (next to the
Newlink)
Change this prototype into a Plugin
Thanks for reading!
From: http://redotheoffice.com/?tag=doctrine-drag-drop-admin-generator-symfony-nestedset
Other: http://halestock.wordpress.com/2010/02/03/symfony-implementing-a-nested-set-part-one/
http://symfonyguide.wordpress.com/2009/10/29/quick-doctrine-nestedset-reference/
相关文章推荐
- [示例] Drag And Drop for FireMonkey (Win & macOS)
- JavaScript: DHTML API,Drag & Drop for Images and Layers
- XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop
- Javascript Drag and drop for touch devices
- MFC Drag & Drop
- ASP.NET Atlas实现网站模块(版块)拖放(Drag & Drop)效果
- Python3学习(一)-基础、数据类型、变量、字符串和编码、list&tuple、if、for、while、dict、set、函数与参数
- ASP.NET Ajax Drag and Drop Table Columns Extender Control/拖拽表列
- target is null for setProperty(null, "x", [Ljava.lang.String;@b0c40e)错误异常
- PyQt学习笔记02-drag & drop
- [news] Dolby Digital chosen as standard for China's TVs, set-top boxes
- target is null for setProperty(null, "name", [Ljava.lang.String;@ffc6ae)
- Html5 drag&drop
- SVGElement Drag & Drop
- 人人网首页拖拽上传详解(HTML5 Drag&Drop、FileReader API、FormData)
- HTML5 drag & drop 拖拽与拖放简介
- Draggabilly – 轻松实现拖放功能(Drag & Drop)
- ognl.OgnlException: target is null for setProperty(null, "offset", [Ljava.lang.String;@1667f3c) 解决方法
- ASP.NET AJAX Drag And Drop
- target is null for setProperty(null, "x", [Ljava.lang.String;@b0c40e)错误异常