html(lang='en',ng-app='StarterApp')
  body(layout='column',ng-controller='AppCtrl')
    .main-fab
      md-button.md-fab.md-accent +
    md-toolbar.md-tall(layout='column')
      span(flex)
      .md-toolbar-tools
        .fill-height(layout='row',flex)
          .md-toolbar-item.md-breadcrumb(ng-hide='toggleSearch')
            span(ng-click='toggleSearch = !toggleSearch') Angular Material Table
          span(flex,ng-hide='toggleSearch')
          md-input-container(flex,style='padding-left:88px;',ng-show='toggleSearch')
            input#searchinput(type='text',ng-model='search',show-focus="toggleSearch")
          .md-toolbar-item.md-tools(layout='row')
            a.md-button.md-default-theme(href='#', ng-click='toggleSearch = !toggleSearch')
              i.ion-android-search
    md-content(layout='column',flex,ng-click='toggleSearch=false')
      md-table(headers="headers", content="content", sortable="sortable", filters="search", custom-class="custom", thumbs="thumbs", count="count")
      
// md-table jade template
#md-table-template(ng-hide='true')
  table.md-table(md-colresize)
      thead
          tr.md-table-headers-row
              th.md-table-header(ng-repeat='h in headers')
                  a(href='#',ng-if='handleSort(h.field)',ng-click='reverse=!reverse;order(h.field,reverse)') {{h.name}} 
                      i.ion-android-arrow-dropup(ng-show='reverse && h.field == predicate')
                      i.ion-android-arrow-dropdown(ng-show='!reverse && h.field == predicate')
                  span(ng-if='!handleSort(h.field)') {{h.name}}
              th.md-table-header
      tbody
          tr.md-table-content-row(ng-repeat='c in content | filter:filters | startFrom:tablePage*count | limitTo: count')
              td
                .md-table-thumbs(ng-repeat='h in headers',ng-if='h.field == thumbs')
                  div(style="background-image:url({{c.thumb}})")
              td.md-table-content(ng-repeat='h in headers',ng-class='customClass[h.field]',ng-if='h.field != thumbs') {{(h.field.indexOf('date') > 0) ? $filter('date')(c[h.field]) : c[h.field];}}
              td.md-table-td-more
                  md-button(aria-label='Info')
                      i.ion-android-more-vertical
  .md-table-footer(layout="row")
      span.md-table-count-info Rows per page : 
          a(href='#',ng-click='goToPage(0); count=10') 10
          | ,
          a(href='#',ng-click='goToPage(0); count=25') 25
          | ,
          a(href='#',ng-click='goToPage(0); count=50') 50
          | ,
          a(href='#',ng-click='goToPage(0); count=100') 100
          | (current is {{count}})
      span(flex)
      span(ng-show='nbOfPages() > 1')
          md-button.md-primary.md-hue-2(ng-disabled='tablePage==0',ng-click='tablePage=tablePage-1',aria-label='Previous Page')
              i.ion-chevron-left(style="font-size:16px;")
          a(href='#',ng-repeat='i in getNumber(nbOfPages()) track by $index')
              md-button.md-primary.md-hue-2.md-table-footer-item(ng-click='goToPage($index)')
                  span(ng-class="{ 'md-table-active-page': tablePage==$index}") {{$index+1}}
          md-button.md-primary.md-hue-2(ng-disabled='tablePage==nbOfPages()-1',ng-click='tablePage=tablePage+1',aria-label='Next Page')
              i.ion-chevron-right(style="font-size:16px;")
View Compiled
a {
  text-decoration: none;
}

i {
  vertical-align: middle;
  font-size: 24px;
}

.main-fab {
  position:absolute;
  z-index:20;
  font-size:30px;
  top:100px;
  left:24px;
  transform:scale(.88,.88);
}

.md-breadcrumb {
  padding-left:88px;  
}

.JCLRgrip:first-child {
  left:105px!important;
  display: none!important;
}

.JColResizer th:first-child {
  width: 105px!important;
}

.md-table {
  min-width: 100%;
  border-collapse: collapse;
}

.md-table tbody tr:hover, .md-table tbody tr:focus {
  cursor:pointer;
  background-color:rgba(63,81,181,0.2);
}

.md-table-header {
  border-bottom: 1px solid rgb(230,230,230);
  color: rgb(130,130,130);
  text-align: left;
  font-size: 0.75em;
  font-weight: 700;
  padding: 16px 16px 16px 0;
}

.md-table-header a{
  text-decoration: none;
  color: inherit;
}

.md-table-content {
  white-space: nowrap;
  font-size: 0.8em;
  padding: 16px 16px 16px 0;
  height: 72px;
}

.md-table-td-more {
  max-width:72px;
  width:72px;
  padding:16px;
}

.md-table-thumbs {
  max-width: 104px;
  width: 104px;
  padding: 16px 32px;
}

.md-table-thumbs div {
  overflow:hidden;
  width: 40px;
  height:40px;
  border-radius:20px;
  border: 1px solid rgba(0,0,0,0.2);
  background-size:cover;
  box-shadow: 0 8px 10px rgba(0,0,0,.3);
  -webkit-box-shadow: 0 8px 10px rgba(0,0,0,.1);
}

.md-table-footer {
  height:40px;
  padding-left: 32px;
  padding-right: 32px;
}

.md-table-count-info {
  line-height:40px;
  font-size:.75em;
}

.md-table-footer-item {
  width: 40px;
  height: 40px;
  vertical-align:middle;
}

.md-table-active-page {
  font-weight: 700;
}

.bold {
  font-weight: 700;
}

.grey {
  color: grey;
}

md-input-container.md-default-theme .md-input {
  color: white;
  border-color: white;
  margin-top: 24px;
}
var app = angular.module('StarterApp', ['ngMaterial']); 

app.controller('AppCtrl', ['$scope', function($scope){
  $scope.toggleSearch = false;
  $scope.headers = [
    {
      name:'',
      field:'thumb'
    },{
      name: 'Name', 
      field: 'name'
    },{
      name:'Description', 
      field: 'description'
    },{
      name: 'Last Modified', 
      field: 'last_modified'
    }
  ];
  
  $scope.content = [
    {
      thumb:'https://i.pinimg.com/736x/1f/3c/9d/1f3c9d6421dce57699938ce02a005482.jpg', 
      name: 'Bruno Mars', 
      description: 'Human',
      last_modified: 'Jun 5, 2014'
    },{
      thumb:'https://cdn.vox-cdn.com/thumbor/bgaFTjV7tU65h8wC15YO8onjzZk=/217x89:1172x626/1600x900/cdn.vox-cdn.com/uploads/chorus_image/image/56334983/at_at_2.0.jpg', 
      name: 'AT-AT', 
      description: 'Robot',
      last_modified: 'Jun 5, 2014'
    },{
      thumb:'https://www.rollingstone.com/wp-content/uploads/2019/11/mark-ronson-soundtrack.jpg', 
      name: 'Mark Ronson', 
      description: 'Human',
      last_modified: 'Jun 5, 2014'
    },{
      thumb:'https://25.media.tumblr.com/61ebf04c3cc7a84944aa0246e902f2a7/tumblr_mm35b87dGz1qmwrnuo1_1280.jpg', 
      name: 'Daft Punk', 
      description: 'Human-Robot',
      last_modified: 'Jun 5, 2014'
    },{
      thumb:'http://thatgrapejuice.net/wp-content/uploads/2014/03/lady-gaga-that-grape-juice-televisionjpg.jpg', 
      name: 'Lady Gaga', 
      description: 'Undefined',
      last_modified: 'Jun 5, 2014'
    }
  ];
  
  $scope.custom = {name: 'bold', description:'grey',last_modified: 'grey'};
  $scope.sortable = ['name', 'description', 'last_modified'];
  $scope.thumbs = 'thumb';
  $scope.count = 3;
}]);

app.directive('mdTable', function () {
  return {
    restrict: 'E',
    scope: { 
      headers: '=', 
      content: '=', 
      sortable: '=', 
      filters: '=',
      customClass: '=customClass',
      thumbs:'=', 
      count: '=' 
    },
    controller: function ($scope,$filter,$window) {
      var orderBy = $filter('orderBy');
      $scope.tablePage = 0;
      $scope.nbOfPages = function () {
        return Math.ceil($scope.content.length / $scope.count);
      },
      	$scope.handleSort = function (field) {
          if ($scope.sortable.indexOf(field) > -1) { return true; } else { return false; }
      };
      $scope.order = function(predicate, reverse) {
          $scope.content = orderBy($scope.content, predicate, reverse);
          $scope.predicate = predicate;
      };
      $scope.order($scope.sortable[0],false);
      $scope.getNumber = function (num) {
      			    return new Array(num);
      };
      $scope.goToPage = function (page) {
        $scope.tablePage = page;
      };
    },
    template: angular.element(document.querySelector('#md-table-template')).html()
  }
});

//UNCOMMENT BELOW TO BE ABLE TO RESIZE COLUMNS OF THE TABLE
/*
app.directive('mdColresize', function ($timeout) {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      scope.$evalAsync(function () {
        $timeout(function(){ $(element).colResizable({
          liveDrag: true,
          fixed: true
          
        });},100);
      });
    }
  }
});
*/

app.directive('showFocus', function($timeout) {
  return function(scope, element, attrs) {
    scope.$watch(attrs.showFocus, 
      function (newValue) { 
        $timeout(function() {
            newValue && element.focus();
        });
      },true);
  };    
});

app.filter('startFrom',function (){
  return function (input,start) {
    start = +start;
    return input.slice(start);
  }
});

External CSS

  1. //ajax.googleapis.com/ajax/libs/angular_material/0.7.1/angular-material.min.css
  2. https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css

External JavaScript

  1. https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.10/angular.min.js
  3. //ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular-animate.min.js
  4. //ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular-aria.min.js
  5. //ajax.googleapis.com/ajax/libs/angular_material/0.7.1/angular-material.min.js
  6. https://greggman.com/downloads/examples/colresizable/colResizable-1.5.min.js