2012-09-06 13 views
15

Sto usando la vista ad albero di KendoUI e voglio dare all'utente la possibilità di filtrarlo. C'è anche una demo che fa quello che voglio (http://demos.kendoui.com/web/treeview/api.html)Filtro KendoUI TreeView

Il problema è che il filtro viene applicato solo alla 1a gerarchia di TreeView , quindi se il testo del filtro è presente in un bambino ma non in quello genitore, il bambino non verrà visualizzato.

Esempio:

  • Articolo 1
  • Articolo 2
    • Articolo xzy
    • abc Articolo

Se il testo di ricerca sarebbe "abc", no l'oggetto sarebbe visualizzato. Invece mi piacerebbe avere il seguente risultato:

  • Articolo 2
    • abc Articolo

Qualcuno sa come fare questo? Questo è il codice che sto usando:

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); 

risposta

7

Aggiornamento 2016/01/13: V'è ora un argomento della guida che mostra how to perform TreeView filtering based on a user string.

È necessario filtrare manualmente i DataSource secondari, in modo che vengano visualizzati solo i nodi necessari. Avere diversi dataTextField s per i diversi livelli rende più difficile da comprendere, quindi questo codice utilizza solo il campo text. Inoltre, poiché questo filtraggio viene eseguito sul lato client, si presuppone che siano stati caricati tutti i nodi.

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

look funziona solo se esiste un nodo (bisogno di modificare per gestire il caso in cui sono presenti più nodi con stesso testo) con testo che corrisponde esattamente al testo del filtro. Diciamo che se il testo di un nodo è "Item abc" e se l'utente inserisce "abc" come testo del filtro, findByText ("abc") restituisce null mentre cerca di far corrispondere il testo del nodo esatto. correggimi se la mia ipotesi era sbagliata. –

+0

davvero sì. se è necessario associare liberamente i nodi, è possibile utilizzare [jQuery contiene selettore] (http://api.jquery.com/contains-selector/) in questo modo: '$ (". k-in: contains ('photo ') ")' –

+0

Provato jQuery contiene selettore, ma il problema è che cerca solo i nodi che sono espansi (resi in HTML) e non corrisponderà ai nodi figli dei nodi compressi. Qualche altra alternativa per questo? –

11

ho trovato un modo per rendere questo accada solo utilizzando i selettori di jQuery per nascondere e mostrare i nodi secondari necessari.

La prima cosa è quando si crea la tua vista ad albero, aggiungere questo parametro per le opzioni:

loadOnDemand: true

In questo modo l'albero renderà tutte le HTML delle tue nodi figlio prima di essere richiesto , consentendo in tal modo di utilizzare jQuery per navigare.

Ecco il codice jQuery che ho lavorato che filtra i nodi che non corrispondono, apre il gruppo di nodi che corrispondono e li mostra.

$("#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

+! per questo. L'unica cosa che dovevo fare era estendere jQuery contiene per renderlo insensibile al maiuscolo/minuscolo. – eadam

+0

Questo è ottimo, ma ho una vista ad albero che arriva fino a 4 livelli e questo codice sembra cercare solo i primi due livelli .. come faccio a cercare l'intero albero? – user2206329

+0

Questo è ottimo, ma ho una vista ad albero che scende a 4 livelli, sembra che stia cercando l'intero albero, ma non mostri nulla .. qualcosa a che fare con l'elemento trovato che si trova 4 livelli in basso e i genitori non essere visto? come faccio a mostrare i genitori? – user2206329

5

Per più di 4 livelli traverse tutti i genitori di tipo UL e LI e spettacolo call().

$("#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

Questa è l'unica soluzione che ha funzionato per me. –

+0

Grazie per questa soluzione. L'unica cosa è che non è stato nascosto i nodi che non corrispondevano, quindi l'ho cambiato un po ': '$ (" # treeview-standards .k-in "). Closest (" li "). Hide();' e ha funzionato perfettamente Molto più veloce della soluzione fornita dalla documentazione di Kendo. – Sunden

0

Prima di tutto. KendoTreeView è un controllo di livello molto basso rispetto a Teleriks RadDropDownTree di ASP.NET http://www.telerik.com/help/aspnet-ajax/dropdowntree-overview.html (intendo ovviamente il js!) L'avrebbe dovuto prendere questo per jquery/kendo ... è necessario per migliorare questo filtro, in modo da se si preferisce una corretta filtrazione su dataitem invece di "findByText", che fa:

.1) trova tutti DataItems .2) controlla il vostro condizioni (qui minuscola contiene sul valore/testo) .3) voce di bandiera, genitori bandiera .4) ripulire, rimuovere nodi lasciati in albero da un genitore

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

Questa versione cerca l'intera albero, non fa distinzione tra maiuscole e minuscole e nasconde i nodi che non contengono la query di ricerca (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

Se ho letto bene la domanda, si tratta di filtrare i dati nella vista e non la vista ad albero stessa. Potrebbe essere fatto da ricorsione.

ricorsione esempio, che funziona:

<!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>