How to filter data-tables using two or more dependent drop-down list?

11,071

Solution 1

Thanks for your reply. I'm working on Data-Table with PHP and I want Server-Side Processing to fetch data from database.

I'm posting my code here,

I found solution for this:

<div class="panel panel-default" id="refresh">
    <div class="panel-heading">
        <b>Defects List</b>
    </div>
    <div class="panel-body">
        <form id="form-filter" class="form-horizontal">
            <div class="row">
                <div class="col-md-3">
                  <label>Area:</label>
                  <?php echo $form_area; ?>
                </div>
                <div class="col-md-3">
                  <label>Cluster:</label>
                  <?php echo $form_cluster; ?>
                </div>
                <div class="col-md-3">
                    <label>Timeframe:</label>
                    <?php echo $form_timeframe; ?>
                </div>  
                <div class="col-md-3">
                    <label>Status:</label>
                    <?php echo $form_defect_status; ?>
                </div>
            </div><br>
            <div class="row">
                <div class="col-md-3" style="display: none;">
                    <label>FUP Start Date:</label>
                    <div class="input-group date">
                        <div class="input-group-addon">
                            <i class="fa fa-calendar"></i>
                        </div>
                        <input type="text" name="startdate" class="form-control" id="datepickerfilter1" placeholder ="dd/mm/yyyy"/>
                    </div>
                </div>
                <div class="col-md-3" style="display: none;">
                    <label>FUP End Date:</label>
                    <div class="input-group date">
                        <div class="input-group-addon">
                            <i class="fa fa-calendar"></i>
                        </div>
                        <input type="text" name="enddate" class="form-control" id="datepickerfilter2" placeholder ="dd/mm/yyyy"/>
                    </div>
                </div>
                <div class="col-sm-6 pull-right" style="text-align: right;">
                    <label>&nbsp;</label><br>
                    <button type="button" id="btn-filter" class="btn btn-primary" style="margin: 0 0px;">Filter</button>
                    <button type="button" id="btn-reset" class="btn btn-default" style="margin: 0 30px;">Reset</button>
                </div>
            </div>
        </form>
    </div>
    <div class="panel-body">
    <table id="defect_view" class="table table-striped table-bordered" cellspacing="0" width="100%">
        <thead>
                <tr>
                <th>ID</th>
                <th>Date</th>
                <th>Subject</th>
                <th>Address1</th>
                <th>Cluster</th>
                <th>Assign to</th>
                <th>FUP-Date</th>
                <th>Timeframe</th>
                <!-- <th>Landlord</th> -->
                <th>Status</th>
                <th>Action</th>

                </tr>
            </thead>
            <tfoot>
                <th>ID</th>
                <th>Date</th>
                <th>Subject</th>
                <th>Address1</th>
                <th>Cluster</th>
                <th>Assign to</th>
                <th>FUP-Date</th>
                <th>Timeframe</th>
                <!-- <th>Landlord</th> -->
                <th>Status</th>
                <th>Action</th> 
            </tfoot>
        </table>
    </div>
</div>

SCRIPT:

<script type="text/javascript">
  var defect_view_var;

$(document).ready(function() {

    defect_view_var = $('#defect_view').DataTable({ 

        "processing": true, //Feature control the processing indicator.
        "serverSide": true, //Feature control DataTables' server-side processing mode.
        "order": [], //Initial no order.

        // Load data for the table's content from an Ajax source
        "ajax": {
            "url": "<?php echo site_url('Property/ajax_list_for_defects')?>",
            "type": "POST",
            "data": function ( data ) {
                data.area = $('#area').val();
                data.cluster = $('#cluster').val();
                data.timeframe = $('#timeframe').val();
                data.defect_status = $('#defect_status').val();
                data.startdate = $('#datepickerfilter1').val();
                data.enddate = $('#datepickerfilter2').val();
            }
        },
        "lengthMenu": [[50, 100, 200, -1], [50, 100, 200, "All"]],
        //Set column definition initialisation properties.
        "columnDefs": [
        { 
            "targets": [ 0, 9 ], //first column / numbering column
            "orderable": false, //set not orderable
        },
        ],

    });

    $('#btn-filter').click(function(){ //button filter event click
        defect_view_var.ajax.reload();  //just reload table
    });
    $('#btn-reset').click(function(){ //button reset event click
        $('#form-filter')[0].reset();
        // document.getElementById('form-filter').reset();
        // defect_view_var.ajax.reload();  //just reload table
        window.location.reload();
    });

});
</script>

Codeigniter Model:

private function _get_datatables_query()
    {

        //add custom filter here
        // if($this->input->post('startdate') && $this->input->post('enddate'))
        // {
        //  $this->db->where("'FUPdate' BETWEEN 'startdate' AND 'enddate'");
        // }
        if($this->input->post('area'))
        {
            $this->db->like('area_name', $this->input->post('area'));
        }
        if($this->input->post('cluster'))
        {
            $clustersID['cluster']=$this->input->post('cluster');
            if(!empty($clustersID['cluster'])){
              // Array contains values, everything ok
              $clusterString = implode(',', $clustersID['cluster']);
            }
            foreach ($clustersID['cluster'] as $clusterStr) {
                $this->db->like('cluster_name', $clusterStr);
            }

        }
        if($this->input->post('timeframe'))
        {
            $this->db->like('timeframe_name', $this->input->post('timeframe'));
        }
        if($this->input->post('defect_status'))
        {
            $this->db->like('defect_status_name', $this->input->post('defect_status'));
        }
        if($this->input->post('startdate'))
        {
            $this->db->like('FUPdate', $this->input->post('startdate'));
        }
        if($this->input->post('enddate'))
        {
            $this->db->like('FUPdate', $this->input->post('enddate'));
        }

        $this->db->from($this->Property_Defect_View);
        $i = 0;

        foreach ($this->Property_Defect_search as $item) // loop column 
        {
            if($_POST['search']['value']) // if datatable send POST for search
            {

                if($i===0) // first loop
                {
                    $this->db->group_start(); // open bracket. query Where with OR clause better with bracket. because maybe can combine with other WHERE with AND.
                    $this->db->like($item, $_POST['search']['value']);
                }
                else
                {
                    $this->db->or_like($item, $_POST['search']['value']);
                }

                if(count($this->Property_Defect_search) - 1 == $i) //last loop
                    $this->db->group_end(); //close bracket
            }
            $i++;
        }

        if(isset($_POST['order'])) // here order processing
        {
            $this->db->order_by($this->Property_Defect_order[$_POST['order']['0']['column']], $_POST['order']['0']['dir']);
        } 
        else if(isset($this->order))
        {
            $order = $this->order;
            $this->db->order_by(key($order), $order[key($order)]);
        }
    }

Controller:

public function DefectList()
    {   
        $user = $this->ion_auth->user()->row();
        $data['username'] = $user->username;

        $data['user_id'] = $user->id;
        $user_id = $user->id;
        $data['groupId'] = $this->l->groupId($user_id);
        $data['group'] = $data['groupId']['0']->group_id;
        $data['title'] = 'Defect List';

        $areas = $this->defects->get_list_areas();
        $clusters = $this->defects->get_list_clusters();
        $timeframes = $this->defects->get_list_timeframes();
        $defect_statuss = $this->defects->get_list_defect_statuss();

        $areaList = array('' => 'All Areas');
        foreach ($areas as $area) {
            $areaList[$area] = $area;
        }
        $data['form_area'] = form_dropdown('',$areaList,'','name="area" id="area" class="form-control select2"');

        $clusterList = array('' => 'All Clusters');
        foreach ($clusters as $cluster) {
            $clusterList[$cluster] = $cluster;
        }
        $data['form_cluster'] = form_dropdown('',$clusterList,'','name="cluster" id="cluster" class="form-control select2" multiple=""');

        $timeframeList = array('' => 'All Timeframes');
        foreach ($timeframes as $timeframe) {
            $timeframeList[$timeframe] = $timeframe;
        }
        $data['form_timeframe'] = form_dropdown('',$timeframeList,'','name="timeframe" id="timeframe" class="form-control select2"');

        $defect_statusList = array('' => 'All Status');
        foreach ($defect_statuss as $defect_status) {
            $defect_statusList[$defect_status] = $defect_status;
        }
        $data['form_defect_status'] = form_dropdown('',$defect_statusList,'','name="defect_status" id="defect_status" class="form-control select2"');


        $this->load->view('template/header', $data);
        $this->load->view('Property/defect_view', $data);
        $this->load->view('template/footer');
    }

    public function ajax_list_for_defects()
    {
        $list = $this->defects->get_datatables();
        $data = array();
        // $no = $_POST['start'];
        foreach ($list as $defects) {
            // $no++;

            $start= $defects->defect_start_date; 
            $start_date = str_replace('/', '-', $start); 
            $startdate=date('d/m/Y', strtotime($start_date)); 

            $follow= $defects->defect_followup_date; 
            $followup = str_replace('/', '-', $follow); 
            $followupdate=date('d/m/Y', strtotime($followup));

            $row = array();
            $row[] = $defects->defect_id;
            $row[] = $startdate;
            $row[] = $defects->defect_subject;
            $row[] = $defects->property_address_1;
            $row[] = $defects->cluster_name;
            $row[] = $defects->users;
            $row[] = $followupdate;
            $row[] = $defects->timeframe_name;
            $row[] = $defects->defect_status_name;
            $row[] = '<a href="'.base_url('property/defectDetails/'.$defects->defect_id).'" style="text-decoration: none;" class="btn btn-info btn-xs">View 
                    <!-- <i class="fa fa-eye" aria-hidden="true" title="View Defect" ></i> -->
                    </a>';

            $data[] = $row;
        }

        $output = array(
                        "draw" => $_POST['draw'],
                        "recordsTotal" => $this->defects->count_all(),
                        "recordsFiltered" => $this->defects->count_filtered(),
                        "data" => $data,
                );
        //output to json format
        echo json_encode($output);
    }

I put my whole code here, so that will help others.

Thanks.

Solution 2

It is important to recognise the difference between .search() and .column().search()

One issue that you have here is that you're using .search() as if it is acting subtractively on the currently filtered set of data. In reality, each call of the .search() function simply runs on the original set of data, so it will only ever return a dataset with 1 filter applied.

To get around this, your best option is to search specific columns for specific values, and take advantage of the chaining available on .column().search()

I would suggest changing your approach to the dropdowns to use data attributes for the column that they wished to filter, for instance:

<select class="table-filter" name="area_id" data-column-filter="2">
    <option></option>
</select>
<select class="table-filter" name="cluster_id" data-column-filter="3">
    <option></option>
</select>

Where the data-column-filter attribute is the index of the column that you want to filter.

You can then write a simple event listener for changes on all relevant select boxes. We can even test the select box to see if it is a multi-select box, and react the event accordingly - we can get an array of the values chosen, and then join them together into a workable regex statement:

$('.table-filter').on('change',function(){
    $('.table-filter').each(function(){

        var filterColumn = $(this).data('column-filter');
        var filterValue = $(this).val();

        if($(this).is('[multiple]'])){
            var filterValuesExpression = filterValue.join('|');
            dataTable.column(filterColumn).search(filterValuesExpression, true, false );
        }else{
            dataTable.column(filterColumn).search(filterValue);
        }
    });

    dataTable.draw();
});

In terms of the logic you use to determine which boxes should and should not be part of the filter at any one time (which boxes are dependent on which others), this is quite separate from DataTables itself.

Solution 3

The following approach relies on a random set of data including fictitious relationships between Area and City/Cluster in order to re populate the cities select list each time a different area is selected.

I commented the code to explain the proceedings as best as possible.

HIH

var infoText = "";
            var relationships = {};
            $(document).ready(function() {
                var columns = [
                    {"data": "Date"},
                    {"data": "Type"},
                    {"data": "ASYS"},
                    {"data": "Address1"},
                    {"data": "Area"},
                    {"data": "City"},
                    {"data": "Status"},
                    {"data": "Landlord"},
                    {"data": "Rooms"}
                ];
                /*generate random relationships between area and cities*/
                generateRelationships();

                var data = generateRandomData(columns);
                var dataTable = $('#exampleProp').DataTable({
                    "data": data,
                    "columns": columns,
                    ordering: false
                });

                $('#areaId').on('change', function() {
                    var selectedAreaId = $(this).val();
                    if (this.value !== '') {
                        if (this.value == 1) {
                            dataTable.column(4).search("Midlands & East of England").draw();
                        } else {
                            dataTable.column(4).search("North East, Yorkshire & Humberside").draw();
                        }

                        /*trigger city filter*/
                        /*make the options related to this area become "selected"*/
                        $('#cluster_id option').each(function() {
                            if ($(this).val() !== '')
                                if (relationships[selectedAreaId].includes($(this).val())) {
                                    $(this).css('display', 'block');
//                                $(this).prop('selected', true);
                                }
                                else {
                                    $(this).css('display', 'none');
//                                $(this).prop('selected', false);
                                }
                        });
                    }
                    else {
                        $('#cluster_id option').css('display', 'block');
                        dataTable.column(4).search('').draw();
                    }
                });
                $('#cluster_id').on('change', function(e) {

                    var searchString = 'City (';
                    /*here we catch the currently selected cities to pass to the search() method*/
                    var selectedOptions = $(this).children('option').filter(':selected');
                    selectedOptions.each(function(i) {
                        searchString += $(this).val();
                        /*i use | assuming you need OR instead of AND for the city multiselect*/
                        searchString += (i === selectedOptions.length - 1 ? ''/*^_^*/ : '|');
                    });
                    //DON'T INCLUDE NEXT LINE THERE -> /*^_^*/, I'LL THROW ERROR WHEN SELECTION IS EMPTY
                    searchString += ")";
                    /*search for selected values using regex is the way to filter in multi select*/
                    dataTable.column(5).search(searchString, true).draw();
                });
                $('#prop_type').on('change', function() {
                    dataTable.column(1).search(this.value).draw();
                });
                $('#prop_status').on('change', function() {
                    dataTable.column(6).search(this.value).draw();
                });
                /*area-city relationship info - NOT NECESSARY*/
                var infoP = $('<p style="background: lightblue"><b>FICTICIOUS RELATIONSHIPS INFO</b><br></p>');
                infoP.append(infoText);
                $('#exampleProp_wrapper').after(infoP);
            });

            /*relate each area to a (in this case random) group of cities*/
            /*maybe the relationships generated by the following code are not near your real life scenarios,
             * for example, I'm assuming there exist only 2 areas and a city can be related to more than 1 area,
             * again this is just for testing purposes, you have to device a way (if you don't have it already
             * of relating these two entities on the client side in order to make the cascading filter work */

            function generateRelationships() {
                $('#areaId option').each(function() {
                    var areaId = $(this).val();
                    if (areaId !== '') {
                        infoText += ("Area <b>" + $(this).text() + "</b> is related to cities ");
                        relationships[areaId] = [];
                        $('#cluster_id option').each(function() {
                            var clusterId = $(this).val();
                            if (clusterId !== '')
                                if (Math.random() > .5) {
                                    relationships[areaId].push(clusterId);
                                    infoText += ("<b><u>" + clusterId + "</u></b> ");
                                }
                        });
                        infoText += "<br>";
                    }
                });
            }

            /*generate test data set*/
            function generateRandomData(columns) {
                
                var data = [];
                var colCount = columns.length;
                for (var i = 0; i < 6; i++) {
                    var tr = {};
                    for (var j = 0; j < colCount; j++) {
                        var area;
                        if (columns[j].data === 'Area') {
                            var r = Math.random();

                            tr['Area'] = r < .5 ? "Midlands & East of England" : "North East, Yorkshire & Humberside";
                            area = r < .5 ? 1 : 2;
                        }
                        else if (columns[j].data === 'City') {
                            
                            var randomCity = relationships[area][Math.floor(Math.random() * relationships[area].length)];
                            tr[columns[j].data] = columns[j].data + " " + randomCity;
                        }
                        else
                            tr[columns[j].data] = columns[j].data + " " + Math.ceil(Math.random() * 6);
                    }
                    data.push(tr);
                }
                return data;
            }
.SideNav{
                position: fixed;
                height: 100vh;
                width: 20vw;
                background: red;
                top: 0;
                left: 0
            }
            span{
                margin-left: 30vw
            }

            td{
                text-align: center
            }

            #cluster_id{
                height: 140px
            }
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="//cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<div class="panel panel-default" id="refresh">
            <div class="panel-heading">
                <b>Property List</b>
            </div>
            <div class="panel-body">
                <div class="col-md-3">
                    <label>Area:</label>
                    <select class="form-control select2" name="area_id" id="areaId">
                        <option value="">ALL</option>
                        <option value="1">Midlands & East of England</option>
                        <option value="2">North East, Yorkshire & Humberside</option>
                    </select>
                </div>
                <div class="col-md-3">
                    <label>Cluster:</label>
                    <select multiple="multiple" class="form-control select2" name="cluster_id[]" id="cluster_id">
                        <option value="">ALL</option>
                        <option value="1">City 1</option>
                        <option value="2">City 2</option>
                        <option value="3">City 3</option>
                        <option value="4">City 4</option>
                        <option value="5">City 5</option>
                        <option value="6">City 6</option>
                    </select>
                </div>
                <div class="col-md-3">
                    <label>Type:</label>
                    <select class="form-control" name="property_type" id="prop_type">
                        <option value="">ALL</option>
                        <option>Type 1</option>
                        <option>Type 2</option>
                        <option>Type 3</option>
                        <option>Type 4</option>
                        <option>Type 5</option>
                        <option>Type 6</option>
                    </select>
                </div>
                <div class="col-md-3">
                    <label>Stage:</label>
                    <select class="form-control" name="property_status" id="prop_status">
                        <option>ALL</option>
                        <option>Stage 1</option>
                        <option>Stage 2</option>
                        <option>Stage 3</option>
                        <option>Stage 4</option>
                        <option>Stage 5</option>
                        <option>Stage 6</option>
                    </select>
                </div>
            </div>
            <div class="panel-body">
                <table id="exampleProp" class="table table-striped table-bordered" cellspacing="0" width="100%"></table>
            </div>
            <div class="modal fade" id="myModal">

            </div>
        </div>

Solution 4

This is an example how it can be done with angular.js

Set ng-app in your html tag

    <html ng-app="myApp">

Set the requierd angular.js file

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>

css

<style>
.pagination a {
    color: black;
    float: left;
    padding: 8px 16px;
    text-decoration: none;
    transition: background-color .3s;
}

.pagination a.active {
    background-color: #4CAF50;
    color: white;
}

th > input[type='text']
{
    width: 90%;
}

.table {
  //border-collapse: collapse;
  border-collapse: separate;

}

thead th,tbody th {
  border-bottom: 1px solid;
    border-color: #eae7e7;

}

thead tr:first-child {

    height: 30px;
    background: white; /* For browsers that do not support gradients */
    background: -webkit-linear-gradient(white, #f2f2f2); /* For Safari 5.1 to 6.0 */
    background: -o-linear-gradient(white, #f2f2f2); /* For Opera 11.1 to 12.0 */
    background: -moz-linear-gradient(white, #f2f2f2); /* For Firefox 3.6 to 15 */
    background: linear-gradient(white, #f2f2f2); /* Standard syntax (must be last) */
}
thead tr:nth-child(2), tfoot tr:first-child  {

    height: 30px;
    background: white; /* For browsers that do not support gradients */
    background: -webkit-linear-gradient(#f2f2f2, white); /* For Safari 5.1 to 6.0 */
    background: -o-linear-gradient(#f2f2f2, white); /* For Opera 11.1 to 12.0 */
    background: -moz-linear-gradient(#f2f2f2, white); /* For Firefox 3.6 to 15 */
    background: linear-gradient(#f2f2f2, white); /* Standard syntax (must be last) */
}


thead td, thead th, tbody td,tbody th{
  border-left: 1px solid;
  border-color: #eae7e7;
  padding: 5px 10px;

}
.table td:first-child, .table th:first-child {
  border-left: none;
}

.icon-sort {

    background-position: -313px -119px;
}
.icon-sort.reverse {

    background-position: -288px -120px;
}


.icon-unsorted {
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAOCAYAAAD5YeaVAAABGUlEQVR4AZWQAUfEYBzGC07fILfrbnfgqG1jmxliDitmYIaxb9Y3CEIEVHDaUGMfYF8gIyBqbd7eH7wWofB6/J7nN+x/IIRQbz6fH8p3slgsrkl4uv8QNU071XX9wTAMQcLTD6bi2WazubUsq3ddV5AwPftU1tbr9Z0UPhGDIHgjYXp2JS+Xy71t2wNCFEV113UxCdOzKznLshvf9z+SJHlp23ZHR8L07Er+6/u/LO96td1u3zmX/BmdjoTp2ZUchmHted4o/16sVqt7KR6TMD27kpumOc/z/EkOvWmaQp7rlYTp2ZU8juOsqqqLoij2UvhyHEeQMD27knl93x+VZXmZpukz9yVh+l+vMQzDrK7rXRzHjyQ83b8BlglBGLw1Kb4AAAAASUVORK5CYII=);
    background-position: center center;
    }
</style>

HTML

<div class="row background-white boxshadows"  ng-controller="myCtrl" > 

    <div class="span12" style="margin-bottom:10px">
        <div style="text-align: center;">
            <select name="singleSelect" id="singleSelect" ng-model="kategori">
                <option value="">SET</option> <!-- not selected / blank option -->
                <option value="TO">TO</option> <!-- interpolation -->
                <option value="FR">FR</option>
                <option value="FE">FE</option>
            </select>
                <select name="singleSelect2" id="singleSelect2" ng-model="sit">
                <option value="">LA</option> <!-- not selected / blank option -->
                <option value="101">J</option> <!-- interpolation -->
                <option value="104">B</option>
                <option value="105">J2</option>
                <option value="102">G</option>
                <option value="201">S</option>
                <option value="203">S2</option>
                <option value="205">O</option>
                <option value="106">A</option>
                <option value="108">H</option>
            </select>
        </div>  
   </div>                             
    <table class="table" style="background-white">
        <thead class="background-white">
            <tr>
                <th ng-click="sortBy('id')">        
                    ID
                    <i class="icon-sort" ng-show="propertyName === 'id'" ng-class="{reverse: reverse}"></i>

                    <i class="bootstrap-icon icon-unsorted" ng-hide="propertyName === 'id'" ></i>
                </th>
                <th ng-click="sortBy('l_namn')">
                    L namn
                    <span class="icon-sort" ng-show="propertyName === 'l_namn'" ng-class="{reverse: reverse}"></span>
                    <i class="bootstrap-icon icon-unsorted" ng-hide="propertyName === 'l_namn'" ></i>

                </th>
                <th ng-click="sortBy('ldag')">
                    Leveransdag
                    <span class="icon-sort" ng-show="propertyName === 'ldag'" ng-class="{reverse: reverse}"></span>
                    <i class="bootstrap-icon icon-unsorted" ng-hide="propertyName === 'ldag'" ></i>

                </th>
                <th ng-click="sortBy('l_nr')">
                    L nr
                    <span class="icon-sort" ng-show="propertyName === 'l_nr'" ng-class="{reverse: reverse}"></span>
                    <i class="bootstrap-icon icon-unsorted" ng-hide="propertyName === 'l_nr'"  ></i>
                </th>
                <th ng-click="sortBy('b_nr')">
                    Beställnings nr
                    <span class="icon-sort" ng-show="propertyName === 'b_nr'" ng-class="{reverse: reverse}"></span>
                    <i class="bootstrap-icon icon-unsorted" ng-hide="propertyName === 'b_nr'" ></i>
                    <span class="triangle"  ></span>
                </th>
                <th ng-click="sortBy('f_nr')">
                    F nr
                    <span class="icon-sort" ng-show="propertyName === 'f_nr'" ng-class="{reverse: reverse}"></span>
                    <i class="bootstrap-icon icon-unsorted" ng-hide="propertyName === 'f_nr'"  ></i>
                </th>
            </tr>
            <tr>
                <th>
                    <input ng-model="search.id" id="sok" type="text" />
                </th>
                <th>
                    <input ng-model="search.l_namn" id="sok" type="text" />
                </th>
                <th>
                    <input ng-model="search.ldag" id="sok" type="text"  />
                </th>
                <th>
                    <input ng-model="search.l_nr" id="sok" type="text" />
                </th>
                <th>
                    <input ng-model="search.b_nr" id="sok" type="text" />
                </th>
                <th>
                    <input ng-model="search.f_nr" id="sok" type="text" />
                </th>
            </tr>
        </thead>
        <tfoot>
                <tr>
                    <td>
                    </td>
                    <td>
                        <select name="singleSelect3" id="singleSelect3" ng-model="rows">
                            <option value="">10</option> <!-- not selected / blank option -->
                            <option value="50">50</option><!-- interpolation -->
                            <option value="100">100</option>
                        </select>
                        </td>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
            </tfoot>
        <tbody ng-repeat="x in records | filter:search | orderBy:propertyName:reverse">
            <tr ng-class-odd="'odd'" ng-class-even="'even'">
                <td ng-style="{'background-color': (bgcolor == 'id') ? ($index % 2 === 0 ? '#f2f2f2 ' : '#dbdbdb') : 'auto'}" >
                    <a href="document/{{x.id}}" title="{{x.id}}">{{x.id}} /{{x.sit}} / {{x.kategori}} </a>
                </td>
                <td ng-style="{'background-color': (bgcolor == 'l_namn') ? ($index % 2 === 0 ? '#eeeeee' : '#dbdbdb') : 'auto'}" >
                    <a href="document/{{x.id}}" title="{{x.l_namn}}">{{x.l_namn}}</a>
                </td>
                <td ng-style="{'background-color': (bgcolor == 'ldag') ? ($index % 2 === 0 ? '#eeeeee' : '#dbdbdb') : 'auto'}" >
                    <a href="document/{{x.id}}" title="{{x.ldag}}">{{x.ldag}}</a>
                </td>
                <td ng-style="{'background-color': (bgcolor == 'l_nr') ? ($index % 2 === 0 ? '#eeeeee' : '#dbdbdb') : 'auto'}">
                    <a href="document/{{x.id}}" title=" {{x.l_nr}}"> {{x.l_nr}}</a>
                </td >
                <td ng-style="{'background-color': (bgcolor == 'b_nr') ? ($index % 2 === 0 ? '#eeeeee' : '#dbdbdb') : 'auto'}" >
                    <a href="document/{{x.id}}" title="{{x.b_nr}}"> {{x.b_nr}} </a>
                </td>
                <td  ng-style="{'background-color': (bgcolor == 'f_nr') ? ($index % 2 === 0 ? '#eeeeee' : '#dbdbdb') : 'auto'}" >
                    <a href="document/{{x.id}}" title="{{x.f_nr}}"> {{x.f_nr}} 
                    <i ng-if="x.images > 0"  class="icon-picture pull-right"></i></a>
                </td>
            </tr>
        </tbody>

    </table>

</div>

Javascript

<script>

var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope, $http) {

    //Session data to remember site 
    if("<?= $this->session->userdata('sit'); ?>" != "empty"){
         $scope.sit = "<?= $this->session->userdata('sit'); ?>";
    }
    //Session data to remember kategori 
    if("<?= $this->session->userdata('kategori'); ?>" != "empty"){
         $scope.kategori = "<?= $this->session->userdata('kategori'); ?>";
    }
        //Session data to remember rows 
    if("<?= $this->session->userdata('rows'); ?>" != "empty"){
         $scope.rows = "<?= $this->session->userdata('rows'); ?>";
    }    

    /*
     *To watch single $scope attributes use:
     *$scope.$watch('search.id', function(val) {
     */
    $scope.$watchCollection('[search.id, search.ldag, search.l_nr, search.l_namn, search.b_nr, search.f_nr, kategori, sit, rows ]', function(val){ 
        if (val) {  
        // This is so it works with PHP.. 
        val[6] = angular.isUndefined(val[6]) ? "empty" : val[6];
        val[6] = val[6] == "" ? "empty" : val[6];   
        val[7] = angular.isUndefined(val[7]) ? "empty" :  val[7];
        val[7] = val[7] == "" ? "empty" : val[7];   

          $http({
             method: 'GET',
             url: '<?= base_url('lista/bazooka/') ?>',
             params: {
                 id: val[0], 
                 ldag: val[1], 
                 l_nr: val[2], 
                 l_namn: val[3],
                 b_nr: val[4],
                 f_nr: val[5], 
                 kategori: val[6],
                 sit: val[7],
                 rows: val[8]
                 },
             headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
            }).then(function(response) { 

            var lager = 
                {   
                '101': 'Jo',
                '104' : 'Bo',
                '105' : 'Jö',
                '102' : 'Gö',
                '201' :'Sk',
                '203' : 'Sä',
                '205' : 'Ö',
                '106': 'AH',
                '108' : 'He'
                };

            var data = [];
            if(response.data[0].id){
            angular.forEach(response.data,function(value,index){
                data.push({ 
                    "id" : ""+value.id, 
                    "l_namn" : ""+ value.l_namn,
                    "b_nr" : ""+ value.b_nr, 
                    "f_nr" : ""+  value.f_nr,
                    "ldag" : ""+ value.ldag,
                    "l_nr" : ""+ value.l_nr,
                    "sit" : ""+ lager[value.sit],
                    "kategori" : ""+ value.kategori,
                    "images" : ""+ value.images,
                    });

                });
                }
                $scope.records = data;      
                $scope.sortBy = function(propertyName) {
                    $scope.bgcolor = propertyName;
                    console.log($scope.reverse);
                    $scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false;
                    $scope.propertyName = propertyName;

                };
            });

        }
    });
});

</script>

controller

function bazooka(){

    $this->db->select('f.id, f.ldag, f.l_nr, f.l_namn, f.b_nr, f.f_nr, users.sit, users.kategori');
    $this->db->from('f');

    $this->db->join('users', 'users.id = f.user', 'left');


    if ($this->input->get('kategori') != 'empty') {
        $this->db->where('users.kategori', $this->input->get('kategori'));
    }
    if ($this->input->get('sit') != 'empty') {
        $this->db->where('users.sit', $this->input->get('sit'));
    }
    if($this->input->get('id') OR $this->input->get('id') != ""){
        $this->db->where("f.id" , $this->input->get('id'));
    }
    if($this->input->get('ldag') OR $this->input->get('ldag') != "" ){
        $this->db->like("ldag" , $this->input->get('ldag'));
    }
    if($this->input->get('l_nr') OR $this->input->get('leverantors_nr') != "" ){
        $this->db->like("l_nr" , $this->input->get('l_nr'));
    }
    if($this->input->get('b_nr') OR $this->input->get('b_nr') != "" ){
        $this->db->like("b_nr" , $this->input->get('b_nr'));
    }
    if($this->input->get('l_namn') OR $this->input->get('l_namn') != "" ){
        $this->db->like("l_namn" , $this->input->get('l_namn'));
    }
    if($this->input->get('f_nr') OR $this->input->get('f_nr') != "" ){
        $this->db->like("f_nr" , $this->input->get('f_nr'));
    }
    if($this->input->get('rows') OR $this->input->get('rows') != "" ){
         $rows = $this->input->get('rows');
    }else $rows = 10;
        $this->db->limit($rows);

        $this->db->order_by("id", "DESC");
        $query = $this->db->get();

    foreach ($query->result_array() as $key=>$val) {

        $row[$key] = array(
        "id"=>$val['id'], 
        "ldag"=>$val['ldag'], 
        "l_nr"=>$val['l_nr'],
        "l_namn"=>$val['l_namn'],   
        "b_nr"=>$val['b_nr'],
        "f_nr"=>$val['f_nr'],
        "sit"=>$val['sit'],
        "kategori"=>$val['kategori'],
        "images"=>$this->entries->images_in_file($val['id']));


     }
    $data["my_data"]  =  $row;
    $this->load->view('json/json_example_view', $data);


}
Share:
11,071
Ganesh Aher
Author by

Ganesh Aher

About me, I'm simple and love to code. I made too much mistakes while coding and learned from them. I love to hear music and play chess.

Updated on July 25, 2022

Comments

  • Ganesh Aher
    Ganesh Aher almost 2 years

    I'm trying to apply filters to my data-table with drop-down list box which are dependent. But when i'm trying to select a value from drop-down, data-table takes value from only one drop-down.

    Here is my code:

    Script:

    <script type="text/javascript">
      $(document).ready(function(){
        var dataTable = $('#exampleProp').DataTable({
          "processing": true,
          "serverSide": true,
          "dom": 'lfrtip',
          "ajax": {
            "url": "<?= base_url('Property/fetchProp'); ?>",
            "dataType": "json",
            "type": "POST"
          },
          "lengthMenu": [[50, 100, 200, -1], [50, 100, 200, "All"]],
          // "ordering": false,
        });
    
        $('#areaId').on('change', function(){
          if (this.value == 1) {
            dataTable.search("Midlands & East of England").draw();
          } else {
            dataTable.search("North East, Yorkshire & Humberside").draw();
          }
        });
        $('#cluster_id').on('change', function(){
           dataTable.search(this.value).draw();   
        });
        $('#prop_type').on('change', function(){
           dataTable.search(this.value).draw();   
        });
        $('#prop_status').on('change', function(){
           dataTable.search(this.value).draw();   
        });
    
      });
    </script>
    

    In this, Cluster is dependent on Area, but if I select Area, it filters using area only, and not by cluster.

    Here is the code to pick a cluster list from database:

    $('#areaId').change(function(){
             var form_date =
             $.ajax({
              url: "<?= base_url('Property/clusterlistAddPropertyUse'); ?>",
              data: {areaId:$(this).val()},
              method:'POST',
              dataType: 'html',
              success:function(data){
                  // $('#cluster_id option:selected').each(function(){
                  // $(this).prop('selected', false);
                  // });
                  $('#cluster_id').html(data); 
                  $('.propcluster').multiselect('rebuild');                 
                 }
              }); 
        });
    

    Here is my view code:

    <?php if($this->session->flashdata('success_msg')){ ?>
      <div class="alert alert-success">
        <?php echo $this->session->flashdata('success_msg'); ?>
      </div> 
    <?php } ?>
    
    <?php if($this->session->flashdata('error_msg')){ ?>
      <div class="alert alert-danger">
        <?php echo $this->session->flashdata('error_msg'); ?>
      </div> 
    <?php } ?>
    
    <div class="panel panel-default" id="refresh">
      <div class="panel-heading">
        <b>Property List</b>
      </div>
      <div class="panel-body">
        <div class="col-md-3">
          <label>Area:</label>
          <select class="form-control select2" name="area_id" id="areaId">
            <option>All</option>
            <?php foreach ($areas as $area) { ?>
              <option value="<?= $area->area_id; ?>"><?php echo $area->area_name; ?></option>
            <?php } ?>
          </select>
        </div>
        <div class="col-md-3">
          <label>Cluster:</label>
          <select class="form-control select2" name="cluster_id[]" id="cluster_id">
          <option>All</option>
            <?php foreach ($clusters as $cluster){ ?>
              <option><?php echo $cluster->cluster_name; ?></option>
            <?php } ?>
          </select>
        </div>
        <div class="col-md-3">
          <label>Type:</label>
          <select class="form-control" name="property_type" id="prop_type">
            <option>All</option>
            <?php if ($property_type) { foreach ($property_type as $type) {?>
              <option><?= $type->property_type_name;?></option>
            <?php } } ?>
          </select> 
        </div> 
        <div class="col-md-3">
          <label>Stage:</label>
          <select class="form-control" name="property_status" id="prop_status">
            <option>All</option>   
            <?php foreach ($property_stage as $stage) { ?>  
              <option><?= $stage->stage_name; ?></option>
            <?php } ?>
          </select>
        </div> 
      </div>
      <div class="panel-body">
        <table id="exampleProp" class="table table-striped table-bordered" cellspacing="0" width="100%">
          <thead>
            <tr>
              <th>Code</th>
              <th>Date</th>
              <th>Type</th>
              <th>ASYS</th>
              <th>Address1</th>
              <!-- <th>Area</th> -->
              <th>City</th>
              <th>Status</th>
              <th>Landlord</th>
              <th>Rooms</th>
              <th>Edit</th>
              <th>Action</th>
            </tr>
          </thead>
          <tfoot>
            <tr>
              <th>Code</th>
              <th>Date</th>
              <th>Type</th>
              <th>ASYS No</th>
              <th>Address1</th>
              <!-- <th>Area</th> -->
              <th>City</th>
              <th>Status</th>
              <th>Landlord</th>
              <th>Rooms</th>
              <th>Edit</th>
              <th>Action</th>
            </tr>
          </tfoot>
        </table>
      </div>
      <div class="modal fade" id="myModal">
      <?php include('property_model_view.php'); ?>
      </div>
    </div>
    

    I want to filter data with both area and cluter and then type and stage also.

    Edit: **

    For more details, I'm adding Controller and model code here:

    **

    Model

    public function prop_query()
    {
        # code...
        $this->db->select('property_id, property_code, property_added_date, property_updated_date, property_type, tbl_property_type.property_type_name as type, property_ASYS_no, property_address_1, property_area, tbl_area.area_name as area, property_cluster, tbl_cluster.cluster_name as cluster, property_status, tbl_property_stage.stage_name as stage, property_landlord_id, concat(tbl_landlord.landlord_first_name, tbl_landlord.landlord_middle_name, tbl_landlord.landlord_last_name) as landlord, property_postcode, count(tbl_rooms.room_property_id) as rooms,');
        $this->db->from($this->property);
    
        $this->db->join('tbl_property_type', 'tbl_property.property_type = tbl_property_type.property_type_id', 'left');
        $this->db->join('tbl_area', 'tbl_property.property_area = tbl_area.area_id', 'left');
        $this->db->join('tbl_cluster', 'tbl_property.property_cluster = tbl_cluster.cluster_id', 'left');
        $this->db->join('tbl_property_stage', 'tbl_property.property_status = tbl_property_stage.stage_id', 'left');
        $this->db->join('tbl_landlord', 'tbl_property.property_landlord_id = tbl_landlord.landlord_id', 'left');
        $this->db->join('tbl_rooms', 'tbl_property.property_id = tbl_rooms.room_property_id', 'left');
    
        // $whereArray = array('tbl_property.property_type' => $propertyType, 'tbl_property.property_area' => $area, 'tbl_property.property_status' => $stageId, 'tbl_property.property_cluster' => '$clusterString');
    
        // $this->db->where('tbl_property.property_type', $propertyType);
        // $this->db->where('tbl_property.property_area', $area);
        // $this->db->where('tbl_property.property_status', $stageId);
        // $this->db->where('tbl_property.property_cluster', $clusterString);
    
        $this->db->group_by('tbl_property.property_id');
        // $this->db->order_by("tbl_property.property_updated_date", "DESC");
    
        if (isset($_POST["search"]["value"])) {
            # code...
            $this->db->like("property_id", $_POST["search"]["value"]);
            $this->db->or_like("property_code", $_POST["search"]["value"]);
            $this->db->or_like("property_added_date", $_POST["search"]["value"]);
            $this->db->or_like("tbl_property_type.property_type_name", $_POST["search"]["value"]);
            $this->db->or_like("property_ASYS_no", $_POST["search"]["value"]);
            $this->db->or_like("property_address_1", $_POST["search"]["value"]);
            $this->db->or_like("tbl_area.area_name", $_POST["search"]["value"]);
            $this->db->or_like("tbl_cluster.cluster_name", $_POST["search"]["value"]);
            $this->db->or_like("tbl_property_stage.stage_name", $_POST["search"]["value"]);
            $this->db->or_like("concat(tbl_landlord.landlord_first_name, tbl_landlord.landlord_middle_name, tbl_landlord.landlord_last_name)", $_POST["search"]["value"]);
            $this->db->or_like("property_postcode", $_POST["search"]["value"]);
        }
    
        if (isset($_POST["order"])) {
            # code...
            // $this->db->order_by("tbl_property.property_updated_date", "DESC");
            $this->db->order_by($this->order_column[$_POST['order']['0']['column']], $_POST['order']['0']['dir']);
        } else {
            # code...
            $this->db->order_by("tbl_property.property_updated_date", "DESC");
            // $this->db->order_by($this->order_column[$_POST['order']['0']['column']], $_POST['order']['0']['dir']);
        }
    }
    
    public function prop_datatables()
    {
        # code...
        $this->prop_query();
    
        if ($_POST["length"] != -1) {
            # code...
            $this->db->limit($_POST["length"], $_POST["start"]);
        }
    
        $query = $this->db->get();
    
        return $query->result();
    }
    
    public function prop_filtered_data()
    {
        # code...
        $this->prop_query();
        $query = $this->db->get();
    
        return $query->num_rows();
    }
    
    public function prop_all_data()
    {
        # code...
        $this->db->select("*");
        $this->db->from($this->property);
    
        return $this->db->count_all_results();
    }
    

    Controller:

    public function fetchProp()
    {
        # code...
        $user = $this->ion_auth->user()->row();
        $data['username'] = $user->username;
    
        $data['user_id'] = $user->id;
        $user_id = $user->id;
        $data['groupId'] = $this->l->groupId($user_id);
        $data['group'] = $data['groupId']['0']->group_id;
    
        $fetch_prop = $this->pm->prop_datatables();
    
        $data = array();
    
        foreach ($fetch_prop as $row) {
            # code...
            $sub_array = array();
            $sub_array[] = $row->property_code;
            $sub_array[] = $row->property_added_date;
            $sub_array[] = $row->type;
            $sub_array[] = $row->property_ASYS_no;
            $sub_array[] = $row->property_address_1;
            // $sub_array[] = $row->area;
            $sub_array[] = $row->cluster;
            $sub_array[] = $row->stage;
            $sub_array[] = $row->landlord;
            $sub_array[] = $row->rooms;
    
                }
            }
    
    
            // $sub_array[] = '<a style="text-decoration: none;" href="'.base_url('Property/propertyDetails/'.$row->property_id).'" class="btn-warning btn-xs">View</a>&nbsp;
            // <a style="text-decoration: none;" href="'.base_url('Property/viewRoom/'.$row->property_id).'" class="btn-success btn-xs">Rooms</a>';
    
    
            $data[] = $sub_array;
        }
    
        $output = array(
            "draw" => intval($_POST["draw"]),
            "recordsTotal" => $this->pm->prop_all_data(),
            "recordsFiltered" => $this->pm->prop_filtered_data(),
            "data" => $data
        );
    
        echo json_encode($output);
    }
    

    I'm gone through this link Data-Tables, But it gives result from columns from table only, I'm not showing area column in the table.

    Edit_2:

    While googled, I got this link, Search API (regular expressions), Data table specific column filter with multi select drop down , Individual column searching (select inputs) , I'm trying to achieve result like this, But with Drop-down box.

    Any kind of help is welcome. Thanks in advance.