drag-and-drop - component - angularjs treeview checkbox
AngularJS-¿Cómo hacer un árbol arrastrable? (3)
Eche un vistazo a este ejemplo: http://jsfiddle.net/furf/EJGHX/
Acabo de completar esta solución, por lo que aún no está debidamente documentada, pero debería poder extraerla para su solución.
Necesitarás usar algunas cosas:
- la directiva
ezTree
- para renderizar el árbol - Plugin anidado de Manuele J Sarfatti para jQuery UI
- (opcional) la directiva
uiNestedSortable
- para habilitar nestedSortable desde su plantilla. - código del controlador para actualizar su modelo - consulte
$scope.update
Usando la directiva ezTree
Dada una estructura de datos recursiva:
$scope.data = {
children: [{
text: ''I want to create a tree like structure...'',
children: [{
text: ''Take a look at this example...'',
children: []
}]
}]
};
Esta plantilla construirá el árbol:
<ol>
<li ez-tree="child in data.children at ol">
<div>{{item.text}}</div>
<ol></ol>
</li>
</ol>
La expresión ez-tree
debe escribirse como item in collection at selector
donde item
es el item
iterado (ala ng-repeat
), collection
es la colección de nivel raíz, y selector
es el selector CSS para el nodo dentro de la plantilla donde la directiva debe recurse. El nombre de la propiedad de la terminal de la colección, en este caso, los children
se utilizarán para volver a generar el árbol, en este caso child.children
. Esto podría reescribirse para ser configurable, pero lo dejo como un ejercicio para el lector.
Uso de la directiva uiNestedSortable
<ol ui-nested-sortable="{ listType: ''ol'', items: ''li'', doNotClear: true }"
ui-nested-sortable-stop="update($event, $ui)">
</ol>
El atributo ui-nested-sortable
debe contener una configuración JSON para el complemento anidadoSortable. El complemento requiere que especifique listType
y items
. Mi solución requiere que doNotClear
sea true
. Asignar devoluciones de llamadas a eventos usando ui-nested-sortable-*eventName*
. Mi directiva proporciona argumentos opcionales de $ event y $ ui para las devoluciones de llamada. Consulte la documentación de nestedSortable para otras opciones.
Actualizando tu modelo
Hay más de una manera de despellejar a este gato. Aquí está el mío. En el evento de detención, extrae la propiedad hija del alcance del elemento para determinar qué objeto se movió, la propiedad secundaria del alcance principal del elemento para determinar el destino del objeto y la posición del elemento para determinar la posición del objeto en su destino A continuación, recorre la estructura de datos y elimina el objeto de su posición original y lo inserta en su nueva posición.
$scope.update = function (event, ui) {
var root = event.target,
item = ui.item,
parent = item.parent(),
target = (parent[0] === root) ? $scope.data : parent.scope().child,
child = item.scope().child,
index = item.index();
target.children || (target.children = []);
function walk(target, child) {
var children = target.children,
i;
if (children) {
i = children.length;
while (i--) {
if (children[i] === child) {
return children.splice(i, 1);
} else {
walk(children[i], child)
}
}
}
}
walk($scope.data, child);
target.children.splice(index, 0, child);
};
Quiero crear una estructura tipo árbol donde el usuario pueda arrastrar y soltar hojas. Tengo un punto de partida de la siguiente manera:
HTML
<div ng:controller="controller">
<ul ui-sortable ng-model="items" ui-options="{connectWith: ''.item''}" class="item">
<li ng-repeat="item in items" class="item">
{{ item.name }}
<ul ui-sortable ng-model="item.children" ui-options="{connectWith: ''.item''}" class="item">
<li ng-repeat="item in item.children" class="item">{{ item.name }}</li>
</ul>
</li>
</ul>
<pre>{{ items | json }}</pre>
</div>
<script src="http://code.angularjs.org/1.0.2/angular.min.js"></script>
<script src="https://raw.github.com/angular-ui/angular-ui/master/build/angular-ui.min.js"></script>
CoffeeScript
myapp = angular.module ''myapp'', [''ui'']
myapp.controller ''controller'', ($scope) ->
$scope.items = [
{id: 1, name: ''Item 1'', children: [
{id: 5, name: ''SubItem 1.1'', children: [
{id: 11, name: ''SubItem 1.1.1'', children: []},
{id: 12, name: ''SubItem 1.1.2'', children: []}
]},
{id: 6, name: ''SubItem 1.2'', children: []}
]},
{id: 2, name: ''Item 2'', children: [
{id: 7, name: ''SubItem 2.1'', children: []},
{id: 8, name: ''SubItem 2.2'', children: []}
{id: 9, name: ''SubItem 2.3'', children: []}
]},
{id: 3, name: ''Item 3'', children: [
{id: 10, name: ''SubItem 3.1'', children: []}
]}
]
angular.bootstrap document, [''myapp'']
El código también está en este JSFiddle: http://jsfiddle.net/bESrf/1/
En mi código "real", en lugar de tener solo un nivel para niños, extraje el segundo <ul>
en una plantilla y lo renderizo recursivamente, lo que funciona bien, pero no pude encontrar una manera de hacerlo en JSFiddle.
¿Cuál sería la mejor manera de renderizarlo de manera recursiva y aún permitir el arrastre y la caída que cambiaría la matriz de objetos y subobjetos representados por ng-model?
Leve edición del violín por furf para que funcione en IE.
IE da un error en insertNode cuando el segundo argumento es nulo, entonces cuando este es el caso, se usa appendNode en su lugar.
http://jsfiddle.net/michieljoris/VmtfR/
if (!cursor) parentNode.appendChild(cached.element);
else parentNode.insertBefore(cached.element, cursor);
El complemento ordenado anidado está en línea en el js, porque IE da una discrepancia en el tipo MIME cuando se incluye desde github.
Prueba Angular-NestedSortable, es un complemento de Angularjs que puede ordenar listas anidadas y vincular datos, y no necesita depender de jQuery. https://github.com/jimliu/Angular-NestedSortable