All core objects or "classes" in FooTable are derived from the FooTable.Class object. This object exposes a single
method called extend
which allows you to create a whole new class from a base class (inherit) or to simply override a single method on an existing class.
In this example we will be inheriting the base FooTable.Filtering component, modifying it and then replacing it
with our modified version.
FooTable.MyFiltering = FooTable.Filtering.extend({ // inherit the base class
construct: function(instance){ // override the default constructor
this._super(instance); // call the base constructor
}
});
To make the code more maintainable going forward and easier to understand we will add some properties to our custom filtering component to hold the available options, the default option, and the jQuery wrapper around our dropdown.
FooTable.MyFiltering = FooTable.Filtering.extend({
construct: function(instance){
this._super(instance);
this.statuses = ['Active','Disabled','Suspended']; // the options available in the dropdown
this.def = 'Any Status'; // the default/unselected value for the dropdown (this would clear the filter when selected)
this.$status = null; // a placeholder for our jQuery wrapper around the dropdown
}
});
To create the actual dropdown element and append it to the table we will override the $create
method and generate our markup as required. The base filtering
component exposes the property $form
which is the jQuery wrapper for the form that contains the default search input. Using this we can simply create our
dropdown and append it as required.
$create: function(){
this._super(); // call the base $create method, this populates the $form property
var self = this, // hold a reference to my self for use later
// create the bootstrap form group and append it to the form
$form_grp = $('<div/>', {'class': 'form-group'})
.append($('<label/>', {'class': 'sr-only', text: 'Status'}))
.prependTo(self.$form);
// create the select element with the default value and append it to the form group
self.$status = $('<select/>', { 'class': 'form-control' })
.on('change', {self: self}, self._onStatusDropdownChanged)
.append($('<option/>', {text: self.def}))
.appendTo($form_grp);
// add each of the statuses to the dropdown element
$.each(self.statuses, function(i, status){
self.$status.append($('<option/>').text(status));
});
}
At this point we have the dropdown appearing next to the search input but we still need to handle the change event we bound to above and actually apply the filter. To do
this we will use the addFilter
, removeFilter
and filter
methods.
_onStatusDropdownChanged: function(e){
var self = e.data.self, // get the MyFiltering object
selected = $(this).val(); // get the current dropdown value
if (selected !== self.def){ // if it's not the default value add a new filter
self.addFilter('status', selected, ['status']);
} else { // otherwise remove the filter
self.removeFilter('status');
}
// initiate the actual filter operation
self.filter();
}
So now we have the dropdown, the filter is being added or removed in the change event as required but we also need the dropdown to be able to handle having it's value set
through the options. To do this we hook into the draw
method and check for the 'status' filter and if one exists update the dropdown as required.
draw: function(){
this._super(); // call the base draw method, this will handle the default search input
var status = this.find('status'); // find the status filter
if (status instanceof FooTable.Filter){ // if it exists update the dropdown to reflect the value
this.$status.val(status.query.val());
} else { // otherwise update the dropdown to the default value
this.$status.val(this.def);
}
}
The final step is to simply decide whether the custom filtering should be applied to all tables in the page or just those specified by you. To register your custom filtering
component for all tables in the page you need to use the FooTable.components.register()
method as seen below.
FooTable.components.register('filtering', FooTable.MyFiltering);
If you want to use your custom filtering component for only a single table or specific tables in a multi-table page then you need to make use of the components option. To do this you would provide the option as below when initializing the plugin.
$('.table').footable({
components: {
filtering: FooTable.MyFiltering
}
});
That's it! We now have a custom filter dropdown that is fully integrated with the rest of the filter functionality. The full code can be seen below.
FooTable.MyFiltering = FooTable.Filtering.extend({
construct: function(instance){
this._super(instance);
this.statuses = ['Active','Disabled','Suspended'];
this.def = 'Any Status';
this.$status = null;
},
$create: function(){
this._super();
var self = this,
$form_grp = $('<div/>', {'class': 'form-group'})
.append($('<label/>', {'class': 'sr-only', text: 'Status'}))
.prependTo(self.$form);
self.$status = $('<select/>', { 'class': 'form-control' })
.on('change', {self: self}, self._onStatusDropdownChanged)
.append($('<option/>', {text: self.def}))
.appendTo($form_grp);
$.each(self.statuses, function(i, status){
self.$status.append($('<option/>').text(status));
});
},
_onStatusDropdownChanged: function(e){
var self = e.data.self,
selected = $(this).val();
if (selected !== self.def){
self.addFilter('status', selected, ['status']);
} else {
self.removeFilter('status');
}
self.filter();
},
draw: function(){
this._super();
var status = this.find('status');
if (status instanceof FooTable.Filter){
this.$status.val(status.query.val());
} else {
this.$status.val(this.def);
}
}
});
Followed by either the below to register the component globally for all tables.
FooTable.components.register('filtering', FooTable.MyFiltering);
Or the below to register it for just a single table.
$('.table').footable({
components: {
filtering: FooTable.MyFiltering
}
});