Skip to content
Advertisement

Issue with filtering on dynamically added elements

I have the following code to filter a UL list based on click on another UL.

I will append dynamically some more elements to the bs-glyphicons-list-sub list to be filtered and I need to modify my code for this.

$('.show-fields').click(function(e) {
  e.preventDefault();
  $('.subList').hide();
  var filter = $(this).data('filtro');
  if (filter == "tutti") {
    $('#closer').hide();
    $('.fieldsList').show();
    $('#closer').show();
    $('.subList').show();
  } else {
    $('#closer').hide();
    $('.fieldsList').show().not('li[data-tipo=' + filter + ']').hide();
    $('#closer').show();
    $('.subList').show();
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="bs-glyphicons">
  <ul class="bs-glyphicons-list">
    <li class="show-fields" data-filtro="tutti" data-html="true" title="Visualizza <b>tutti i campi</b>"><span class="glyphicon glyphicon-search"></span><span class="glyphicon-class">Tutti</span></li>
    <li class="show-fields" data-filtro="input" data-html="true" title="Campi basati su template <b>input</b>"><span class="glyphicon glyphicon-log-in"></span><span class="glyphicon-class">Input</span></li>
    <li class="show-fields" data-filtro="textarea" data-html="true" title="Campi su template <b>testo libero</b>"><span class="glyphicon glyphicon-unchecked"></span><span class="glyphicon-class">Testo libero</span></li>
    <li class="show-fields" data-filtro="opzioni" data-html="true" title="Campi su template <b>opzioni</b>"><span class="glyphicon glyphicon-th-list"></span><span class="glyphicon-class">Opzioni</span></li>
    <li class="show-fields" data-filtro="validato" data-html="true" title="Campi su template <b>input validati</b>"><span class="glyphicon glyphicon-filter"></span><span class="glyphicon-class">Input validati</span></li>
    <li data-html="true" title="Aggiungi un campo" data-toggle="modal" id="addField"><span class="glyphicon glyphicon-plus"></span><span class="glyphicon-class">Aggiungi un campo</span></li>
  </ul>
</div>

<ul class="bs-glyphicons-list-sub">
  <li class="fieldsList" data-tipo="input" data-label="Nome" data-value="1" data-description="Qual � il tuo nome di battesimo?" id="fields_nome">
    <span class="glyphicon glyphicon-log-in"></span><span class="glyphicon-class">Nome</span>
  </li>
  <li class="fieldsList" data-tipo="input" data-label="Cognome" data-value="2" data-description="Qual � il tuo cognome? Per le donne il cognome da nubile" id="fields_cognome">
    <span class="glyphicon glyphicon-log-in"></span><span class="glyphicon-class">Cognome</span>
  </li>
  <li class="fieldsList" data-tipo="validato" data-label="Mail" data-value="3" data-description="Indica la tua mail aziendale" id="fields_mail">
    <span class="glyphicon glyphicon-filter"></span><span class="glyphicon-class">Mail</span>
  </li>
  <li class="fieldsList" data-tipo="validato" data-label="Telefono" data-value="4" data-description="Telefono: Un campo testo di massimo 256 caratteri senza formato specifico" id="fields_telefono">
    <span class="glyphicon glyphicon-filter"></span><span class="glyphicon-class">Telefono</span>
  </li>
  <li class="fieldsList" data-tipo="validato" data-label="Codice fiscale" data-value="5" data-description="Codice fiscale: Un campo testo in formato codice fiscale italiano" id="fields_codice-fiscale">
    <span class="glyphicon glyphicon-filter"></span><span class="glyphicon-class">Codice fiscale</span>
  </li>
  <li class="fieldsList" data-tipo="validato" data-label="Data" data-value="6" data-description="Data: Un campo data generico in formato gg/mm/aaaa" id="fields_data">
    <span class="glyphicon glyphicon-filter"></span><span class="glyphicon-class">Data</span>
  </li>
  <li class="fieldsList" data-tipo="validato" data-label="Ora" data-value="7" data-description="Ora: Un campo ora generico in formato hh:mm" id="fields_ora">
    <span class="glyphicon glyphicon-filter"></span><span class="glyphicon-class">Ora</span>
  </li>
  <li class="fieldsList" data-tipo="validato" data-label="Cellulare" data-value="8" data-description="Il tuo cellulare aziendale" id="fields_cellulare-it">
    <span class="glyphicon glyphicon-filter"></span><span class="glyphicon-class">Cellulare</span>
  </li>
  <li class="fieldsList" data-tipo="validato" data-label="Cellulare internazionale" data-value="9" data-description="Cellulare internazionale: Un campo cellulare da minimo 12 massimo 15 cifre che richiede country code all'inizio (formato +############)"
    id="fields_cellulare-ex">
    <span class="glyphicon glyphicon-filter"></span><span class="glyphicon-class">Cellulare internazionale</span>
  </li>
  <li class="fieldsList" data-tipo="textarea" data-label="Indirizzo di domicilio" data-value="13" data-description="Indirizzo di domicilio: dove vivi abitualmente" id="fields_indirizzo2">
    <span class="glyphicon glyphicon-unchecked"></span><span class="glyphicon-class">Indirizzo di domicilio</span>

The line I need to modify is the following:

$('.fieldsList').show().not('li[data-tipo='+filter+']').hide();

where I need to include the elements that I appended after DOM ready. I know about delegated events, I know how to use .on(), what I don’t know is how to apply delegated events binding to the filter function here. The elements I click on are immutable so I don’t think that using .on() on the click event may lead to something useful.

Advertisement

Answer

What you are doing is: Add event handling to elements, which are available at the start ($('.show-fields').click()). DOM elements that are added later don’t trigger this event.

What you need to be doing is: Delegate the click event. By catching the event on the <ul> which is already there at startup and delegating the event handling to the <li> on which the event occurred, you also catch DOM elements inside the <ul> which are added later.

I also deleted the then branch of the if, because you can set the filter for tutti to the empty string and it will work automatically.

console.clear();


$('.show-fields-list').on('click', '.show-fields', function(e) {
  console.log(e)
  e.preventDefault();
  $('.subList').hide();
  var filter = $(this).data('filtro');
  $('#closer').hide();
  $('.fieldsList').show().not('li[data-tipo=' + filter + ']').hide();
  $('#closer').show();
  $('.subList').show();
});

$('#add-new-filter').on('click', function() {
  $('.show-fields-list').append($('<li class="show-fields" data-filtro="' + $('#add-new-filter-filter').val() + '">' + $('#add-new-filter-label').val() + '</li>'))
})

$('#add-new-option').on('click', function() {
  $('.fields').append($('<li class="fieldsList" data-tipo="' + $('#add-new-option-tipo').val() + '">' + $('#add-new-option-label').val() + '</li>'))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<input id="add-new-filter-filter" placeholder="filter">
<input id="add-new-filter-label" placeholder="label">
<button id="add-new-filter">Add new filter</button><br>

<ul class="show-fields-list">
  <li class="show-fields" data-filtro="">Tutti</li>
  <li class="show-fields" data-filtro="input">Input</li>
  <li class="show-fields" data-filtro="textarea">Testo libero</li>
  <li class="show-fields" data-filtro="opzioni">Opzioni</li>
  <li class="show-fields" data-filtro="validato">Input validati</li>
</ul>

<input id="add-new-option-tipo" placeholder="tipo">
<input id="add-new-option-label" placeholder="label">
<button id="add-new-option">Add new option</button><br>

<ul class="fields">
  <li class="fieldsList" data-tipo="input">
    Nome
  </li>
  <li class="fieldsList" data-tipo="input">
    Cognome
  </li>
  <li class="fieldsList" data-tipo="validato">
    Mail
  </li>
  <li class="fieldsList" data-tipo="validato">
    Telefono
  </li>
  <li class="fieldsList" data-tipo="validato">
    Codice fiscale
  </li>
  <li class="fieldsList" data-tipo="validato">
    Data
  </li>
  <li class="fieldsList" data-tipo="validato">
    Ora
  </li>
  <li class="fieldsList" data-tipo="new">
    New
  </li>
  <li class="fieldsList" data-tipo="validato">
    Cellulare
  </li>
  <li class="fieldsList" data-tipo="validato">
    Cellulare internazionale
  </li>
  <li class="fieldsList" data-tipo="textarea">
    Indirizzo di domicilio
  </li>
</ul>
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement