bootstrap-select with custom buttons & add new values on the fly

Theo Itzaris picture Theo Itzaris · Jul 10, 2015 · Viewed 10.2k times · Source

enter image description herei needed to use a dropdown list that could do that functionality:

  1. dynamically fetches and loads values from the database
  2. has an embeded search box
  3. has 2 custom buttons on each Li, one for delete and one for edit.
  4. the search field, if the searched text does not exist, add it on 'enter' press, either on the same select <option> and also on the database with Ajax.

I chose the custom select for @twitter bootstrap 'bootstrap-select' from silviomoreto git repository and because I did not find the functionality that I want i tried to make it on my own.

So, for those that need or would like to add that functionality on their web-apps , I wrote down my solution, which is not the best solution but it works, and I am open to any suggestions to make it work better.

1. step: create a selectpicker with parameters : data-size="5" (show 5 values and the add scrollbar), data-live-search="true" (add the search box on the top) and load the values that I get from db (preferably with ajax):

       <select class="selectpicker typedropdown" data-size="5" data-live-search="true">
                            <?php
                            $counter=0;
                            foreach($eventTypeList as $evType){
                                $counter++;
                                if(is_array($evType)){
                                    echo "<option>".$evType['type_name']."</option>";
                                }else{
                                    echo "<option>".$evType."</option>";
                                }

                            } ?>
                        </select>

2. step: add the custom buttons (edit, delete) (override the prototype function 'createLi')

override the prototype function 'createLi' on your main js file like this:

  $.fn.selectpicker.Constructor.prototype.createLi = function (){..}

Inside :

var generateLI = function (content, index, classes, optgroup) {
        return '<li' + ........

just before the 'return' add the line with tha two button classes :

content += "<div class='removeTypebtn'></div><div class='editTypebtn'></div>";

so that , when you create the li items you also create the two custom buttons on each row.

3. step: catch 'click' events for edit & delete value (also makes an ajax request on the database to update the dbtable)

$(document.body).on('click','.btn-group.typedropdown .dropdown-menu ul li .removeTypebtn',function(event){
        var index = $(event.target).closest( "li" ).data('original-index');//get the item index
        var type_name = $(event.target).closest( "li" ).text();
        deleteType(index,type_name);
    });

in a similar way we catch the 'click' event for the 'edit item', so I omitted it.

now we need to do the interesting part , to delete the selected item from the selectpicker and also make an ajax request to delete it from dbtable. the database is beyond the tutorial scope so , I left it out. pay attention inside the success function how I remove.

function deleteType(index,type_name){
        var url = "<?php echo $domain.$deleteType; ?>";
        data = {'index':index,'type_name':type_name};
        $.ajax({
            cache: false,
            url : url,
            type: "POST",
            data : data,
            success : function(data, textStatus, jqXHR){
                $('.typedropdown').find('[data-original-index=$index]').remove();//remove selected item from selectpicker
            $('.typedropdown').find('option:contains($type_name)').remove();";// remove value also from the hidden select
                $('.selectpicker.typedropdown').selectpicker('val', []);//clear selected
            },
            error : function(xhr, ajaxOptions, thrownError){
                alert(thrownError);
            }
        });
    }

4. step: create the 'add new value' functionality on Enter (as you know the search field only permit searches inside the li's)

so, when we init the selectpicker component , we change the 'noneResultsText' message , by altering the parameter : noneResultsText :

//init selectpicker
    selectPickerType = $('.selectpicker.typedropdown').selectpicker({
        noneResultsText:'Add new {0}',
        selectOnTab: true
    });

so, now whenever we write down a new word that does not exist , we get the message Add new 'myword'

Now we need to catch the click event.

$('.selectpicker.typedropdown').data('selectpicker').$searchbox.on('keydown',function(e){
            if(e.keyCode == 13){
                addNewDropdownValue(e.target.value,'type');
                return false;
            }
        });

and the addNewDropdownValue function : (with an ajax request to dbtable to add the new value) (pay attention into the success function)

function addNewDropdownValue(newValue,tble){
    var url = "<?php echo $domain.$addDropdownValueURL; ?>";
    data = {'newValue':newValue,'tble':tble};
    var loading = $('.loading');
    $.ajax({
        cache: false,
        url : url,
        type: "POST",
        data : data,
        beforeSend: function( xhr ) {
            loading.css('top',screen.height/2);
            loading.css('left',screen.width/2);
            loading.html('<div><img alt="loading..." src="<?php echo $domain; ?>/assets/images/loader/ajax_loader_blue_48.gif" /></div>').show();
        },
        success : function(data, textStatus, jqXHR){
            loading.fadeOut(500);
            $('.selectpicker.".$tble."dropdown').append('<option selected>$newValue</option>');//append new item on the selectpicker
            $('.selectpicker.".$tble."dropdown').val('$newValue');//select the new value
            $('.selectpicker.".$tble."dropdown').selectpicker('refresh');//refresh the selectpicker
            $('.".$tble."dropdown').removeClass('open');//close the selectpicker
        },
        error : function(xhr, ajaxOptions, thrownError){
            alert(thrownError);
        }
    });
}

that's it , now we have a custom bootstrap select-picker with delete and edit buttons on each row and add new text functionality on enter.

please by any means, tell me your opinion on how we can make it work better or if you have any questions.

Answer

Timothy Moody picture Timothy Moody · Jan 5, 2017

How this could be done better is to remove PHP from the equation. In fact, remove any server side code from generating html or DOM elements. This will leave you with two pieces, the javascript to render the UI and the database methods via an API (node.js or the like).

The implementation would look something like the following -

$.ajax({
  url: "/api/databaseCall/",
  success: function(data){

/* 
Build DropDown
the data variable will be a hash or array of returned db results
iterate over them and build UI
*/

    for(var i=0; i < data.results.length; i++){

      var row = '<option id=' + data.results[i].id + '>' + data.results[i].value + '</option>';
      $(".dropdown").append(row);
    } 

  }
});

Angular, react, backbone all are built with this approach in mind. The only one I endorse at this time is backbone.js. Backbone is very easy to learn.

Once you build the UI programmatically with javascript any functionality will be bound automatically using a framework like backbone.