2012-09-06 26 views
15

Estoy utilizando la vista en árbol de KendoUI y quiero dar al usuario la posibilidad de filtrarlo. Incluso hay una demostración que hace lo que quiero (http://demos.kendoui.com/web/treeview/api.html)Filtro KendoUI TreeView

El problema es que el filtro solo se aplica a la 1ª jerarquía de TreeView , por lo tanto, si el texto de filtro está presente en un elemento secundario pero no en el elemento primario, no se mostrará el elemento secundario.

Ejemplo:

  • artículo 1
  • artículo 2
    • artículo xzy
    • ABC Punto

Si el texto de búsqueda sería "abc", sin ítem sería mostrado. En su lugar me gustaría tener el siguiente resultado:

  • artículo 2
    • ABC Punto

¿Alguien sabe cómo hacer esto? Este es el código que estoy utilizando:

var tree_view_data = new kendo.data.HierarchicalDataSource({ 
     transport: { 
      read: { 
       url: "getall/items", 
       dataType: "json" 
      } 
     }, 
     schema: { 
      model: { 
       children: "ChildItems" 
      } 
     } 
    }); 
    //init tree view itself 
    var $treeview = $("#div-treeview").kendoTreeView({ 
     dataSource: tree_view_data, 
     dataTextField: [ "Text", "ChildrenText" ] 
    }); 

    //allow filter of navigation tree 
    var refreshTree = function() { 
     tree_view_data.filter({ 
      field: "Text", //if I would use "ChildrenText" here nothing be displayed at all if filtertext is set 
      operator: "contains", 
      value: $("#tree-text-search").val() 
     }); 
    }; 

    $("#tree-text-search").change(refreshTree).keyup(refreshTree); 

Respuesta

7

actualización 01/13/2016: Ahora hay un tema de ayuda que muestra how to perform TreeView filtering based on a user string.

Debe filtrar manualmente los DataSources secundarios, de modo que solo se muestren los nodos necesarios. Tener diferentes dataTextField s para los diferentes niveles hace que sea más difícil de entender, por lo que este código usa el campo text solamente. Además, como este filtrado se realiza en el lado del cliente, supone que ha cargado todos los nodos.

var treeview = $("#treeview").data("kendoTreeView"), 
    item = treeview.findByText("Item 1.3"), // find the node that will be shown 
    dataItem = treeview.dataItem(item), 
    nodeText = dataItem.text; 

// loop through the parents of the given node, filtering them to only one item 
while (dataItem.parentNode()) { 
    dataItem = dataItem.parentNode(); 
    dataItem.children.filter({ field: "text", operator: "contains", value: nodeText }); 
    nodeText = dataItem.text; 
} 

treeview.dataSource.filter({ field: "text", operator: "contains", value: nodeText }); 
+0

miradas, funciona sólo si existe un nodo (necesidad de ajustar para manejar el caso cuando hay múltiples nodos con un mismo texto) con el texto que coincide exactamente con el texto del filtro. Digamos que si un texto de nodo es "Artículo abc" y si el usuario ingresa "abc" como texto de filtro, findByText ("abc") devuelve nulo a medida que intenta hacer coincidir el texto del nodo exacto. corrígeme si mi suposición es incorrecta. –

+0

de hecho lo hace. si necesita relacionar los nodos, puede usar el selector [jQuery contains] (http://api.jquery.com/contains-selector/) de la siguiente manera: '$ (". k-in: contains ('photo ') ")' –

+0

Intento jQuery contiene el selector, pero el problema es que solo busca los nodos que se expanden (representados en HTML) y no coincidirá con los nodos secundarios de los nodos contraídos. ¿Alguna otra alternativa para esto? –

11

Encontré una manera de hacer que esto suceda solo con los selectores jQuery para ocultar y mostrar los nodos secundarios necesarios.

Lo primero es cuando se va a crear su vista en árbol, agregar este parámetro a sus opciones:

loadOnDemand: falsa

De esta manera el árbol hará que todo el HTML de sus nodos hijos antes de ser solicitada , lo que le permite usar jQuery para navegar.

Aquí está el código jQuery que tengo trabajando que filtra los nodos que no coinciden, abre el grupo de nodos que coinciden y los muestra.

$("#searchTextInputField").keyup(function() { 

     var filterText = $("#searchTextInputField").val(); 

     if(filterText !== "") { 
      $("#myTree .k-group .k-group .k-in").closest("li").hide(); 
      $("#myTree .k-group .k-group .k-in:contains(" + filterText + ")").each(function() { 
       $(this).closest("ul").show(); 
       $(this).closest("li").show(); 
      }); 
     } else { 
      $("#myTree .k-group").find("ul").hide(); 
      $("#myTree .k-group").find("li").show(); 
     } 
    }); 
+0

+! para esto. Lo único que tuve que hacer fue extender jQuery contiene para que no distinga entre mayúsculas y minúsculas. – eadam

+0

Esto es genial, pero tengo una vista de árbol que baja a 4 niveles, y este código solo parece buscar los dos primeros niveles ... ¿cómo hago para buscar todo el árbol? – user2206329

+0

Esto es genial, pero tengo una vista de árbol que baja a 4 niveles, parece que está buscando todo el árbol, pero no muestra nada ... algo que ver con el elemento que se encuentra a 4 niveles hacia abajo y los padres no ser visto? ¿Cómo logro que muestre a los padres? – user2206329

5

Para más de 4 niveles atraviesa todas las familias de tipo UL y LI y llama a show().

$("#filterText").keyup(function (e) { 
    var filterText = $(this).val(); 

    if (filterText !== "") { 
     $("#treeview-standards .k-group .k-group .k-in").closest("li").hide(); 
     $("#treeview-standards .k-group .k-group .k-in:contains(" + filterText + ")").each(function() { 
      $(this).parents("ul, li").each(function() { 
       $(this).show(); 
      }); 
     }); 
    } else { 
     $("#treeview-standards .k-group").find("ul").hide(); 
     $("#treeview-standards .k-group").find("li").show(); 
    } 
}); 
+1

Esta es la única solución que funcionó para mí. –

+0

Gracias por esta solución. Lo único es que no estaba ocultando nodos que no coincidían, así que lo cambié un poco: '$ (" # treeview-standards .k-in "). Closer (" li "). Hide();' y funcionó perfectamente Mucho más rápido que la solución que te brinda la documentación de Kendo. – Sunden

0

Primero de todos. KendoTreeView es un control de muy bajo nivel en comparación con Teleriks RadDropDownTree de ASP.NET http://www.telerik.com/help/aspnet-ajax/dropdowntree-overview.html (me refiero a los js, por supuesto!) El debería haber tomado esto jQuery/kendo ... necesitaba mejorar este filtro, por lo si lo prefiere filtrado adecuado en dataitem en lugar de "findByText", esto hace:

0.1) encuentra todos los dataitems 0.2) comprueba sus condiciones (aquí en minúsculas contiene el valor/texto) 0.3) artículo bandera, padres bandera 0.4) a limpiar, eliminar nodos que quedan en el árbol por el padre

that.nodeFilter = { logic: "or", filters: [] }; 
that.nodeFilter.filters.push({ field: "hidden", operator: "eq", value: false }); 
tree.element.find(".k-in").each(function() { 
    var dItem = tree.dataItem($(this).closest("li")); 
    dItem.hidden = false; 
    if (dItem[that.options.dataValueField].toLowerCase().indexOf(searchTerm) != -1 || 
     dItem[that.options.dataTextField].toLowerCase().indexOf(searchTerm) != -1) { 
     that.nodeFilter.filters.push({ field: that.options.dataValueField, operator: "eq", value: dItem[that.options.dataValueField] }) 
     while (dItem.parentNode()) { 
      dItem = dItem.parentNode(); 
      dItem.hidden = false; 
      that.nodeFilter.filters.push({ field: that.options.dataValueField, operator: "eq", value: dItem[that.options.dataValueField] }) 
     } 
    } else { 
     dItem.hidden = true; 
    } 
}); 
tree.dataSource.filter(that.nodeFilter); 
tree.element.find(".k-in").each(function() { 
    var node = $(this).closest("li"); 
    var dataItem = tree.dataItem(node); 
    if (dataItem.hidden) { 
     tree.remove(node); 
    } 
}); 
0

Esta versión busca en el conjunto tree, no distingue entre mayúsculas y minúsculas y oculta nodos que no contienen la consulta de búsqueda (jQuery 1.8+).

$("#search").keyup(function (e) { 
     var query = $(this).val(); 

     if (query !== "") { 
      $("#tree-view .k-in").closest("li").hide(); 
      $("#tree-view .k-item .k-in:Contains(" + query + ")").each(function() { 
       $(this).parents("ul, li").each(function() { 
        $(this).show(); 
       }); 
      }); 
     } else { 
      $("#tree-view .k-group").find("ul").hide(); 
      $("#tree-view .k-group").find("li").show(); 
     } 
    }); 

jQuery.expr[":"].Contains = jQuery.expr.createPseudo(function (arg) { 
    return function (elem) { 
     return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0; 
    }; 
}); 
0

Si leo bien la pregunta, se trata de filtrar los datos en la vista y no la vista en árbol. Podría hacerse por recursión.

recursividad ejemplo que funciona:

<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <meta charset="utf-8"/> 
 
    <title>Kendo UI Snippet</title> 
 

 
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.common.min.css"/> 
 
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.rtl.min.css"/> 
 
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.silver.min.css"/> 
 
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.mobile.all.min.css"/> 
 

 
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script> 
 
    <script src="https://kendo.cdn.telerik.com/2018.1.117/js/kendo.all.min.js"></script> 
 
</head> 
 
<body> 
 
    <div class="demo-section k-content"> 
 
    <div id="treeview1"></div> 
 
    <div id="showit"></div> 
 
    <div id="treeview2"></div> 
 
    </div> 
 
<script> 
 
    // 
 
    // Define hierarchical data source 
 
    // 
 
    var mydata = new kendo.data.HierarchicalDataSource({ 
 
     name: "Food", items: [ 
 
     { name: "Meat", items: 
 
     [ 
 
      { name: "Pork" }, 
 
      { name: "Beef" } 
 
     ] 
 
     }, 
 
     { name: "Vegetables", items: 
 
     [ 
 
      { name: "Pepper" }   
 
     ] 
 
     } 
 
     ] 
 
    }); 
 

 
    // 
 
    // When debugging 
 
    //  
 
    var debug=false; 
 
    
 
    // 
 
    // Find and return Item when found. 
 
    // 
 
    function FindByName(items, myName) 
 
    { 
 
     //Query definition 
 
     var query = kendo.data.Query.process(items, { 
 
       filter: { 
 
       logic: "or", 
 
       filters: [{ 
 
        field: "name", 
 
        value: myName, 
 
        operator: "eq" 
 
       }] 
 
       } 
 
      }); 
 
     
 
     if (debug) $("#showit").html($("#showit").html()+" found:" + JSON.stringify(query.data)); 
 
     
 
     // 
 
     // return Item when found. 
 
     // 
 
     if (query.data != "")  
 
     return query.data; //ready 
 
     else 
 
     { 
 
     // 
 
     // if sub-items, search further 
 
     // 
 
     for (let i=0; i<items.length; i++)    
 
     { 
 
      if (debug) $("#showit").html($("#showit").html()+" test:" + JSON.stringify(items[i])); 
 
      if (items[i].items!=null) 
 
      {   
 
      if (debug) $("#showit").html($("#showit").html()+" search sub...."); 
 
      var r = FindByName(items[i].items, myName); 
 
      if (r!=null) return r; //ready, else continue searching further 
 
      }; 
 
     } 
 
     } 
 
     if (debug) $("#showit").html($("#showit").html()+" not found."); 
 
     return null; //nothing found. 
 
    } 
 
    
 
    // 
 
    // print the input 
 
    // 
 
    $("#showit").html($("#showit").html()+" Food:" + JSON.stringify(mydata.options.items)); 
 
    // 
 
    // print the result 
 
    // 
 
    \t var ret=FindByName(mydata.options.items,"Beef"); 
 
    $("#showit").html($("#showit").html()+"<p> Beef:" + JSON.stringify(ret)); 
 
    
 
    $("#treeview1").kendoTreeView({ 
 
     dataSource: mydata.options.items, 
 
     dataTextField: ["name"] 
 
    }); 
 

 
    ret=FindByName(mydata.options.items,"Meat"); 
 
    $("#showit").html($("#showit").html()+"<p> Meat:" + JSON.stringify(ret)); 
 
    ret=FindByName(mydata.options.items,"Pepper"); 
 
    $("#showit").html($("#showit").html()+"<p> Pepper:" + JSON.stringify(ret)); 
 
    ret=FindByName(mydata.options.items,"Vegetables"); 
 
    $("#showit").html($("#showit").html()+"<p> Vegetables:" + JSON.stringify(ret)); 
 
    // 
 
    // Example: bind return value [ret] to treeview. 
 
    // 
 
    $("#treeview2").kendoTreeView({ 
 
     dataSource: ret, 
 
     dataTextField: ["name"] 
 
    }); 
 
</script> 
 
</body> 
 
</html>