I am using jsTree (3.3.2) to display a hierarchical structure of entities. The way I have it configured is so that it loads the json with the complete structure, taking as the root node the node to which the authenticated user belongs, but it is not really functional for me; On the server side, through a recursive function, I generate the json that implies making multiple queries to the database. I need your help to configure the function in such a way that it can differentiate the load of the root node, from the call to the load of the child nodes (direct to the root node). I have seen implementations on the plugin page, but they differentiate the root node by setting the value of id='#' and I don't think it will work for me, since I need to have the id of each of the nodes to complete the rest of the views .
This is my current code, I have removed the settings section from the context menu.
$('#arbol').jstree({
'core': {
'strings': {
'Loading ...': 'Cargando ...'
},
'force_text': true,
'themes': {
'responsive': true,
'variant': 'small',
'stripes': false
},
'multiple': false,
'animation': 135,
'expand_selected_onload': false,
'worker': true,
'dblclick_toggle': true,
'data': {
'url': Routing.generate('app_renderArbol')
},
'check_callback': function(o, n, p, i, m) {
// Esta funcion chequea el tipo de nodo seleccionado para evitar se convierta en draggable
},
},
'plugins': ["state", "dnd", "contextmenu"],
'state': {'key': 'arbol_state'},
'dnd': {inside_pos: "last"}
}).on('move_node.jstree', function(e, data) {
e.preventDefault();
$.ajax({
datatypes: 'GET',
method: 'JSON',
url: Routing.generate('estructuraOrganizativa_moverCMF', {'cmf': data.node.id, 'gbt': data.parent}),
beforeSend: function() {
$('#indicador').addClass('cargando-satisfactorio').fadeIn('fast');
}
}).done(function(data) {
$('#indicador').html(data.message);
}).fail(function(jqXHR) {
$('#indicador').addClass('cargando-error').html(jqXHR.responseText);
data.instance.refresh();
}).always(function(jqXHR, type) {
if (type !== 'success') {
$('#indicador').fadeOut(5500, function() {
$(this).removeClass('cargando-error').html("<span class='glyphicon glyphicon-time'></span> Cargando...");
});
} else {
$('#indicador').fadeOut(4500, function() {
$(this).removeClass('cargando-error').html("<span class='glyphicon glyphicon-time'></span> Cargando...");
});
}
});
}).on('select_node.jstree', function(event, data) {
event.preventDefault();
if (data && data.selected && data.selected.length) {
var nodo = data.instance.get_selected(true)[0];
cargarVistaCentral(nodo); // esta trae de vuelta la vista central de la app basándose en el nodo seleccionado
} else {
return false;
}
});
These are the functions in the controller to return the json array (an action and a recursive function). Of course, if the js could be properly implemented, the controller would be much simpler: obtain the root node from the authenticated user's data, and the rest of the child nodes (direct children) easier to obtain: $nodo->getChildren(true)
, well now it is part of the model.
public function renderArbolAction(Request $request)
{
if ($request->isXmlHttpRequest())
{
$estructuraOrganizativa = $this->getUser()->getEstructuraOrganizativa();
$arbol[] = array(
'id' => $estructuraOrganizativa->getId(),
'text' => $estructuraOrganizativa->getTitle(),
'icon' => 'icon-sitemap', // \AppBundle\Utils\UI::getIconForTreeNode($estructuraOrganizativa)
'data' => array(
'tipoEstructura' => array(
'id' => $estructuraOrganizativa->getTipoEstructuraOrganizativa()->getId(),
'nombre' => $estructuraOrganizativa->getTipoEstructuraOrganizativa()->getNombre(),
),
'parent_id' => '#',
'rol_id' => $this->getUser()->getRol()->getId(),
),
'state' => array(
'opened' => true,
'selected' => false
),
'li_attr' => array(
'title' => $estructuraOrganizativa->getTitle(),
),
' a_attr' => array(
'href' => '#',
),
'children' => $this->BuildChildsRecursive($estructuraOrganizativa),
);
$response = new Response(json_encode($arbol));
$response->headers->set('Content-Type', 'application/json');
return $response;
} else
{
throw $this->createNotFoundException("Recurso no encontrado");
}
}
private function BuildChildsRecursive(EstructuraOrganizativa $nodo)
{
$nodosParaJSON = array();
$repositoryEstructuraOrganizativa = $this->getDoctrine()->getRepository('AppBundle:EstructuraOrganizativa');
$cantidadHijos = $repositoryEstructuraOrganizativa->childCount($nodo, true);
if ($cantidadHijos === 0)
{
return array();
} else
{
$hijos = $repositoryEstructuraOrganizativa->children($nodo, true);
foreach ($hijos as $hijo)
{
if (in_array($hijo->getTipoEstructuraOrganizativa()->getId(), array(7, 8)))
{
if (!$this->get('security.authorization_checker')->isGranted(array('ROLE_ESP_NAC', 'ROLE_ESP_PROV', 'ROLE_CONS_NAC', 'ROLE_CONS_PROV')))
{
continue;
}
}
$nodosParaJSON[] = array(
'id' => $hijo->getId(),
'text' => $hijo->getTitle(),
'icon' => \AppBundle\Utils\UI::getIconForTreeNode($hijo),
'data' => array(
'tipoEstructura' => array(
'id' => $hijo->getTipoEstructuraOrganizativa()->getId(),
'nombre' => $hijo->getTipoEstructuraOrganizativa()->getNombre(),
),
'parent_id' => $hijo->getParent()->getId(),
'rol_id' => $this->getUser()->getRol()->getId(),
),
'state' => array(
'opened' => false,
'selected' => false
),
'li_attr' => array(
'title' => $hijo->getTitle(),
),
' a_attr' => array(
'href' => '#',
),
'children' => $this->BuildChildsRecursive($hijo),
);
}
return $nodosParaJSON;
}
}
Well, I have found the solution and it is based on the comparison of the node id with the character '#' as I saw in the official documentation; basically my solution is based on having two urls where the
json
one waitingjsTree
to generate the tree comes from.and on the server side the two actions that correspond to each routing:
I should note that the Entity
EstructuraOrganizativa
uses doctine extensions that make it easy for me to work with tree-like structures, and even has functions to return an entirehtml
nest that you can most likelyjsTree
use, but the level of customization my structure tree requires, so as a series of data that I store for each node, it does not help me that itRepository
generates the html.