I am using jsTree (3.3.2) to show a hierarchical structure of entities. The way I have it configured is to load the json with the complete structure taking as root node the node to which the authenticated user belongs, but it really is not functional for me; On the server side, by means of a recursive function, I generate the json which implies making multiple queries to the database. I need your help to configure the function so 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 in the pluggin page, but they make the differentiation of the root node by setting the value of the id = '#' and I do not think it serves 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 configuration 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 you can properly implement the js, the driver would be much simpler: get the root node from the data of the authenticated user, and the rest of the nodes children (direct children) simpler to obtain: $nodo->getChildren(true)
, well, it's already 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;
}
}