Added .component syntax in ng-xos-lib

Change-Id: Icc6ff26cff1369038cc9684612f742af0a78c799
diff --git a/src/ui_components/dumbComponents/alert/alert.component.js b/src/ui_components/dumbComponents/alert/alert.component.js
index 9b60def..948c851 100644
--- a/src/ui_components/dumbComponents/alert/alert.component.js
+++ b/src/ui_components/dumbComponents/alert/alert.component.js
@@ -102,43 +102,41 @@
   </example>
   **/
 
-  .directive('xosAlert', function(){
-    return {
-      restrict: 'E',
-      scope: {
-        config: '=',
-        show: '=?'
-      },
-      template: `
-        <div ng-cloak class="alert alert-{{vm.config.type}}" ng-hide="!vm.show">
-          <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">
-            <span aria-hidden="true">&times;</span>
-          </button>
-          <p ng-transclude></p>
-        </div>
-      `,
-      transclude: true,
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: function($timeout){
+  .component('xosAlert', {
+    restrict: 'E',
+    bindings: {
+      config: '=',
+      show: '=?'
+    },
+    template: `
+      <div ng-cloak class="alert alert-{{vm.config.type}}" ng-hide="!vm.show">
+        <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">
+          <span aria-hidden="true">&times;</span>
+        </button>
+        <p ng-transclude></p>
+      </div>
+    `,
+    transclude: true,
+    bindToController: true,
+    controllerAs: 'vm',
+    controller: function($timeout){
 
-        if(!this.config){
-          throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');
-        }
+      if(!this.config){
+        throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');
+      }
 
-        // default the value to true
-        this.show = this.show !== false;
-        
-        this.dismiss = () => {
-          this.show = false;
-        }
+      // default the value to true
+      this.show = this.show !== false;
 
-        if(this.config.autoHide){
-          let to = $timeout(() => {
-            this.dismiss();
-            $timeout.cancel(to);
-          }, this.config.autoHide);
-        }
+      this.dismiss = () => {
+        this.show = false;
+      }
+
+      if(this.config.autoHide){
+        let to = $timeout(() => {
+          this.dismiss();
+          $timeout.cancel(to);
+        }, this.config.autoHide);
       }
     }
   })
diff --git a/src/ui_components/dumbComponents/field/field.component.js b/src/ui_components/dumbComponents/field/field.component.js
index 21b2f4e..a246f9f 100644
--- a/src/ui_components/dumbComponents/field/field.component.js
+++ b/src/ui_components/dumbComponents/field/field.component.js
@@ -142,98 +142,96 @@
         </file>
       </example>
     */
-  .directive('xosField', function(RecursionHelper){
-    return {
-      restrict: 'E',
-      scope: {
-        name: '=',
-        field: '=',
-        ngModel: '='
-      },
-      template: `
-        <label ng-if="vm.field.type !== 'object'">{{vm.field.label}}</label>
-            <input
-              xos-custom-validator custom-validator="vm.field.validators.custom || null"
-              ng-if="vm.field.type !== 'boolean' && vm.field.type !== 'object' && vm.field.type !== 'select'"
-              type="{{vm.field.type}}"
-              name="{{vm.name}}"
-              class="form-control"
+  .component('xosField', {
+    restrict: 'E',
+    bindings: {
+      name: '=',
+      field: '=',
+      ngModel: '='
+    },
+    template: `
+      <label ng-if="vm.field.type !== 'object'">{{vm.field.label}}</label>
+          <input
+            xos-custom-validator custom-validator="vm.field.validators.custom || null"
+            ng-if="vm.field.type !== 'boolean' && vm.field.type !== 'object' && vm.field.type !== 'select'"
+            type="{{vm.field.type}}"
+            name="{{vm.name}}"
+            class="form-control"
+            ng-model="vm.ngModel"
+            ng-minlength="vm.field.validators.minlength || 0"
+            ng-maxlength="vm.field.validators.maxlength || 2000"
+            ng-required="vm.field.validators.required || false" />
+            <select class="form-control" ng-if ="vm.field.type === 'select'"
+              name = "{{vm.name}}"
+              ng-options="item.id as item.label for item in vm.field.options"
               ng-model="vm.ngModel"
-              ng-minlength="vm.field.validators.minlength || 0"
-              ng-maxlength="vm.field.validators.maxlength || 2000"
-              ng-required="vm.field.validators.required || false" />
-              <select class="form-control" ng-if ="vm.field.type === 'select'"
-                name = "{{vm.name}}"
-                ng-options="item.id as item.label for item in vm.field.options"
-                ng-model="vm.ngModel"
-                ng-required="vm.field.validators.required || false">
-                </select>
-            <span class="boolean-field" ng-if="vm.field.type === 'boolean'">
-              <a href="#"
-                class="btn btn-success"
-                ng-show="vm.ngModel"
-                ng-click="vm.ngModel = false">
-                <i class="glyphicon glyphicon-ok"></i>
-              </a>
-              <a href="#"
-                class="btn btn-danger"
-                ng-show="!vm.ngModel"
-                ng-click="vm.ngModel = true">
-                <i class="glyphicon glyphicon-remove"></i>
-              </a>
-            </span>
-            <div
-              class="panel panel-default object-field"
-              ng-if="vm.field.type == 'object' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"
-              >
-              <div class="panel-heading">{{vm.field.label}}</div>
-              <div class="panel-body">
-                <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">
-                  <xos-field
-                    name="k"
-                    field="{label: vm.formatLabel(k), type: vm.getType(v)}"
-                    ng-model="v">
-                  </xos-field>
-                </div>
-                <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">
-                  <xos-field
-                    name="k"
-                    field="{
-                      label: v.label || vm.formatLabel(k),
-                      type: v.type,
-                      validators: v.validators
-                    }"
-                    ng-model="vm.ngModel[k]">
-                  </xos-field>
-                </div>
+              ng-required="vm.field.validators.required || false">
+              </select>
+          <span class="boolean-field" ng-if="vm.field.type === 'boolean'">
+            <a href="#"
+              class="btn btn-success"
+              ng-show="vm.ngModel"
+              ng-click="vm.ngModel = false">
+              <i class="glyphicon glyphicon-ok"></i>
+            </a>
+            <a href="#"
+              class="btn btn-danger"
+              ng-show="!vm.ngModel"
+              ng-click="vm.ngModel = true">
+              <i class="glyphicon glyphicon-remove"></i>
+            </a>
+          </span>
+          <div
+            class="panel panel-default object-field"
+            ng-if="vm.field.type == 'object' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"
+            >
+            <div class="panel-heading">{{vm.field.label}}</div>
+            <div class="panel-body">
+              <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">
+                <xos-field
+                  name="k"
+                  field="{label: vm.formatLabel(k), type: vm.getType(v)}"
+                  ng-model="v">
+                </xos-field>
+              </div>
+              <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">
+                <xos-field
+                  name="k"
+                  field="{
+                    label: v.label || vm.formatLabel(k),
+                    type: v.type,
+                    validators: v.validators
+                  }"
+                  ng-model="vm.ngModel[k]">
+                </xos-field>
               </div>
             </div>
-      `,
-      bindToController: true,
-      controllerAs: 'vm',
-      // the compile cicle is needed to support recursion
-      compile: function (element) {
-        return RecursionHelper.compile(element);
-      },
-      controller: function($attrs, XosFormHelpers, LabelFormatter){
+          </div>
+    `,
+    bindToController: true,
+    controllerAs: 'vm',
+    // the compile cicle is needed to support recursion
+    //compile: function (element) {
+    //  return RecursionHelper.compile(element);
+    //},
+    controller: function($attrs, XosFormHelpers, LabelFormatter){
 
-        if(!this.name){
-          throw new Error('[xosField] Please provide a field name');
-        }
-        if(!this.field){
-          throw new Error('[xosField] Please provide a field definition');
-        }
-        if(!this.field.type){
-          throw new Error('[xosField] Please provide a type in the field definition');
-        }
-        if(!$attrs.ngModel){
-          throw new Error('[xosField] Please provide an ng-model');
-        }
-        this.getType = XosFormHelpers._getFieldFormat;
-        this.formatLabel = LabelFormatter.format;
-
-        this.isEmptyObject = o => o ? Object.keys(o).length === 0 : true;
+      if(!this.name){
+        throw new Error('[xosField] Please provide a field name');
       }
+      if(!this.field){
+        throw new Error('[xosField] Please provide a field definition');
+      }
+      if(!this.field.type){
+        throw new Error('[xosField] Please provide a type in the field definition');
+      }
+      if(!$attrs.ngModel){
+        throw new Error('[xosField] Please provide an ng-model');
+      }
+      this.getType = XosFormHelpers._getFieldFormat;
+      this.formatLabel = LabelFormatter.format;
+
+      this.isEmptyObject = o => o ? Object.keys(o).length === 0 : true;
     }
   })
 
diff --git a/src/ui_components/dumbComponents/form/form.component.js b/src/ui_components/dumbComponents/form/form.component.js
index 4d9169b..9fedb3c 100644
--- a/src/ui_components/dumbComponents/form/form.component.js
+++ b/src/ui_components/dumbComponents/form/form.component.js
@@ -204,82 +204,80 @@
 
   **/
 
-  .directive('xosForm', function(){
-    return {
-      restrict: 'E',
-      scope: {
-        config: '=',
-        ngModel: '='
-      },
-      template: `
-        <form name="vm.{{vm.config.formName || 'form'}}" novalidate>
-          <div class="form-group" ng-repeat="(name, field) in vm.formField">
-            <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>
-            <xos-validation field="vm[vm.config.formName || 'form'][name]" form = "vm[vm.config.formName || 'form']"></xos-validation>
-            <div class="alert alert-info" ng-show="(field.hint).length >0" role="alert">{{field.hint}}</div>
-          </div>
-          <div class="form-group" ng-if="vm.config.actions">
-          <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>
+  .component('xosForm', {
+    restrict: 'E',
+    bindings: {
+      config: '=',
+      ngModel: '='
+    },
+    template: `
+      <form name="vm.{{vm.config.formName || 'form'}}" novalidate>
+        <div class="form-group" ng-repeat="(name, field) in vm.formField">
+          <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>
+          <xos-validation field="vm[vm.config.formName || 'form'][name]" form = "vm[vm.config.formName || 'form']"></xos-validation>
+          <div class="alert alert-info" ng-show="(field.hint).length >0" role="alert">{{field.hint}}</div>
+        </div>
+        <div class="form-group" ng-if="vm.config.actions">
+        <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>
 
-            <button role="button" href=""
-              ng-repeat="action in vm.config.actions"
-              ng-click="action.cb(vm.ngModel, vm[vm.config.formName || 'form'])"
-              class="btn btn-{{action.class}}"
-              title="{{action.label}}">
-              <i class="glyphicon glyphicon-{{action.icon}}"></i>
-              {{action.label}}
-            </button>
-          </div>
-        </form>
-      `,
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: function($scope, $log, _, XosFormHelpers){
+          <button role="button" href=""
+            ng-repeat="action in vm.config.actions"
+            ng-click="action.cb(vm.ngModel, vm[vm.config.formName || 'form'])"
+            class="btn btn-{{action.class}}"
+            title="{{action.label}}">
+            <i class="glyphicon glyphicon-{{action.icon}}"></i>
+            {{action.label}}
+          </button>
+        </div>
+      </form>
+    `,
+    bindToController: true,
+    controllerAs: 'vm',
+    controller: function($scope, $log, _, XosFormHelpers){
 
-        if(!this.config){
-          throw new Error('[xosForm] Please provide a configuration via the "config" attribute');
-        }
-
-        if(!this.config.actions){
-          throw new Error('[xosForm] Please provide an action list in the configuration');
-        }
-
-        if(!this.config.feedback){
-          this.config.feedback =  {
-            show: false,
-            message: 'Form submitted successfully !!!',
-            type: 'success'
-          }
-        }
-
-        this.excludedField = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status'];
-        if(this.config && this.config.exclude){
-          this.excludedField = this.excludedField.concat(this.config.exclude);
-        }
-
-        this.formField = [];
-
-        $scope.$watch(() => this.config, ()=> {
-          if(!this.ngModel){
-            return;
-          }
-          let diff = _.difference(Object.keys(this.ngModel), this.excludedField);
-          let modelField = XosFormHelpers.parseModelField(diff);
-          this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, this.ngModel);
-        }, true);
-
-        $scope.$watch(() => this.ngModel, (model) => {
-          // empty from old stuff
-          this.formField = {};
-          if(!model){
-            return;
-          }
-          let diff = _.difference(Object.keys(model), this.excludedField);
-          let modelField = XosFormHelpers.parseModelField(diff);
-          this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, model);
-        });
-
+      if(!this.config){
+        throw new Error('[xosForm] Please provide a configuration via the "config" attribute');
       }
+
+      if(!this.config.actions){
+        throw new Error('[xosForm] Please provide an action list in the configuration');
+      }
+
+      if(!this.config.feedback){
+        this.config.feedback =  {
+          show: false,
+          message: 'Form submitted successfully !!!',
+          type: 'success'
+        }
+      }
+
+      this.excludedField = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status'];
+      if(this.config && this.config.exclude){
+        this.excludedField = this.excludedField.concat(this.config.exclude);
+      }
+
+      this.formField = [];
+
+      $scope.$watch(() => this.config, ()=> {
+        if(!this.ngModel){
+          return;
+        }
+        let diff = _.difference(Object.keys(this.ngModel), this.excludedField);
+        let modelField = XosFormHelpers.parseModelField(diff);
+        this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, this.ngModel);
+      }, true);
+
+      $scope.$watch(() => this.ngModel, (model) => {
+        // empty from old stuff
+        this.formField = {};
+        if(!model){
+          return;
+        }
+        let diff = _.difference(Object.keys(model), this.excludedField);
+        let modelField = XosFormHelpers.parseModelField(diff);
+        this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, model);
+      });
+
     }
   });
 })();
diff --git a/src/ui_components/dumbComponents/pagination/pagination.component.js b/src/ui_components/dumbComponents/pagination/pagination.component.js
index ddb1eb9..0324751 100644
--- a/src/ui_components/dumbComponents/pagination/pagination.component.js
+++ b/src/ui_components/dumbComponents/pagination/pagination.component.js
@@ -45,69 +45,67 @@
   </example>
   **/
 
-  .directive('xosPagination', function(){
-    return {
-      restrict: 'E',
-      scope: {
-        pageSize: '=',
-        totalElements: '=',
-        change: '='
-      },
-      template: `
-        <div class="row" ng-if="vm.pageList.length > 1">
-          <div class="col-xs-12 text-center">
-            <ul class="pagination">
-              <li
-                ng-click="vm.goToPage(vm.currentPage - 1)"
-                ng-class="{disabled: vm.currentPage == 0}">
-                <a href="" aria-label="Previous">
-                    <span aria-hidden="true">&laquo;</span>
-                </a>
-              </li>
-              <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">
-                <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>
-              </li>
-              <li
-                ng-click="vm.goToPage(vm.currentPage + 1)"
-                ng-class="{disabled: vm.currentPage == vm.pages - 1}">
-                <a href="" aria-label="Next">
-                    <span aria-hidden="true">&raquo;</span>
-                </a>
-              </li>
-            </ul>
-          </div>
+  .component('xosPagination', {
+    restrict: 'E',
+    bindings: {
+      pageSize: '=',
+      totalElements: '=',
+      change: '='
+    },
+    template: `
+      <div class="row" ng-if="vm.pageList.length > 1">
+        <div class="col-xs-12 text-center">
+          <ul class="pagination">
+            <li
+              ng-click="vm.goToPage(vm.currentPage - 1)"
+              ng-class="{disabled: vm.currentPage == 0}">
+              <a href="" aria-label="Previous">
+                  <span aria-hidden="true">&laquo;</span>
+              </a>
+            </li>
+            <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">
+              <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>
+            </li>
+            <li
+              ng-click="vm.goToPage(vm.currentPage + 1)"
+              ng-class="{disabled: vm.currentPage == vm.pages - 1}">
+              <a href="" aria-label="Next">
+                  <span aria-hidden="true">&raquo;</span>
+              </a>
+            </li>
+          </ul>
         </div>
-      `,
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: function($scope){
-        
-        this.currentPage = 0;
+      </div>
+    `,
+    bindToController: true,
+    controllerAs: 'vm',
+    controller: function($scope){
 
-        this.goToPage = (n) => {
-          if(n < 0 || n === this.pages){
-            return;
-          }
-          this.currentPage = n;
-          this.change(n);
+      this.currentPage = 0;
+
+      this.goToPage = (n) => {
+        if(n < 0 || n === this.pages){
+          return;
         }
-
-        this.createPages = (pages) => {
-          let arr = [];
-          for(let i = 0; i < pages; i++){
-            arr.push(i);
-          }
-          return arr;
-        }
-
-        // watch for data changes
-        $scope.$watch(() => this.totalElements, () => {
-          if(this.totalElements){
-            this.pages = Math.ceil(this.totalElements / this.pageSize);
-            this.pageList = this.createPages(this.pages);
-          }
-        });
+        this.currentPage = n;
+        this.change(n);
       }
+
+      this.createPages = (pages) => {
+        let arr = [];
+        for(let i = 0; i < pages; i++){
+          arr.push(i);
+        }
+        return arr;
+      }
+
+      // watch for data changes
+      $scope.$watch(() => this.totalElements, () => {
+        if(this.totalElements){
+          this.pages = Math.ceil(this.totalElements / this.pageSize);
+          this.pageList = this.createPages(this.pages);
+        }
+      });
     }
   })
   .filter('pagination', function(){
diff --git a/src/ui_components/dumbComponents/table/table.component.js b/src/ui_components/dumbComponents/table/table.component.js
index 1e60458..e8f66b4 100644
--- a/src/ui_components/dumbComponents/table/table.component.js
+++ b/src/ui_components/dumbComponents/table/table.component.js
@@ -330,196 +330,193 @@
   </example>
     **/
 
-    .directive('xosTable', function(){
-      return {
-        restrict: 'E',
-        scope: {
-          data: '=',
-          config: '='
-        },
-        template: `
-          <div ng-show="vm.data.length > 0 && vm.loader == false">
-            <div class="row" ng-if="vm.config.filter == 'fulltext'">
-              <div class="col-xs-12">
-                <input
-                  class="form-control"
-                  placeholder="Type to search.."
-                  type="text"
-                  ng-model="vm.query"/>
-              </div>
+    .component('xosTable', {
+      restrict: 'E',
+      bindings: {
+        data: '=',
+        config: '='
+      },
+      template: `
+        <div ng-show="vm.data.length > 0 && vm.loader == false">
+          <div class="row" ng-if="vm.config.filter == 'fulltext'">
+            <div class="col-xs-12">
+              <input
+                class="form-control"
+                placeholder="Type to search.."
+                type="text"
+                ng-model="vm.query"/>
             </div>
-            <table ng-class="vm.classes" ng-hide="vm.data.length == 0">
-              <thead>
-                <tr>
-                  <th ng-repeat="col in vm.columns">
-                    {{col.label}}
-                    <span ng-if="vm.config.order">
-                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">
-                        <i class="glyphicon glyphicon-chevron-up"></i>
-                      </a>
-                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">
-                        <i class="glyphicon glyphicon-chevron-down"></i>
-                      </a>
-                    </span>
-                  </th>
-                  <th ng-if="vm.config.actions">Actions:</th>
-                </tr>
-              </thead>
-              <tbody ng-if="vm.config.filter == 'field'">
-                <tr>
-                  <td ng-repeat="col in vm.columns">
-                    <input
-                      ng-if="col.type !== 'boolean' && col.type !== 'array' && col.type !== 'object' && col.type !== 'custom'"
-                      class="form-control"
-                      placeholder="Type to search by {{col.label}}"
-                      type="text"
-                      ng-model="vm.query[col.prop]"/>
-                    <select
-                      ng-if="col.type === 'boolean'"
-                      class="form-control"
-                      ng-model="vm.query[col.prop]">
-                      <option value="">-</option>
-                      <option value="true">True</option>
-                      <option value="false">False</option>
-                    </select>
-                  </td>
-                  <td ng-if="vm.config.actions"></td>
-                </tr>
-              </tbody>
-              <tbody>
-                <tr ng-repeat="item in vm.data | filter:vm.query:vm.comparator | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">
-                  <td ng-repeat="col in vm.columns" xos-link-wrapper>
-                    <span ng-if="!col.type">{{item[col.prop]}}</span>
-                    <span ng-if="col.type === 'boolean'">
-                      <i class="glyphicon"
-                        ng-class="{'glyphicon-ok': item[col.prop], 'glyphicon-remove': !item[col.prop]}">
-                      </i>
-                    </span>
-                    <span ng-if="col.type === 'date'">
-                      {{item[col.prop] | date:'H:mm MMM d, yyyy'}}
-                    </span>
-                    <span ng-if="col.type === 'array'">
-                      {{item[col.prop] | arrayToList}}
-                    </span>
-                    <span ng-if="col.type === 'object'">
-                      <dl class="dl-horizontal">
-                        <span ng-repeat="(k,v) in item[col.prop]">
-                          <dt>{{k}}</dt>
-                          <dd>{{v}}</dd>
-                        </span>
-                      </dl>
-                    </span>
-                    <span ng-if="col.type === 'custom'">
-                      {{col.formatter(item)}}
-                    </span>
-                    <span ng-if="col.type === 'icon'">
-                      <i class="glyphicon glyphicon-{{col.formatter(item)}}">
-                      </i>
-                    </span>
-                  </td>
-                  <td ng-if="vm.config.actions">
-                    <a href=""
-                      ng-repeat="action in vm.config.actions"
-                      ng-click="action.cb(item)"
-                      title="{{action.label}}">
-                      <i
-                        class="glyphicon glyphicon-{{action.icon}}"
-                        style="color: {{action.color}};"></i>
+          </div>
+          <table ng-class="vm.classes" ng-hide="vm.data.length == 0">
+            <thead>
+              <tr>
+                <th ng-repeat="col in vm.columns">
+                  {{col.label}}
+                  <span ng-if="vm.config.order">
+                    <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">
+                      <i class="glyphicon glyphicon-chevron-up"></i>
                     </a>
-                  </td>
-                </tr>
-              </tbody>
-            </table>
-            <xos-pagination
-              ng-if="vm.config.pagination"
-              page-size="vm.config.pagination.pageSize"
-              total-elements="vm.data.length"
-              change="vm.goToPage">
-              </xos-pagination>
-          </div>
-          <div ng-show="(vm.data.length == 0 || !vm.data) && vm.loader == false">
-             <xos-alert config="{type: 'info'}">
-              No data to show.
-            </xos-alert>
-          </div>
-          <div ng-show="vm.loader == true">
-            <div class="loader"></div>
-          </div>
-        `,
-        bindToController: true,
-        controllerAs: 'vm',
-        controller: function(_, $scope, Comparator){
+                    <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">
+                      <i class="glyphicon glyphicon-chevron-down"></i>
+                    </a>
+                  </span>
+                </th>
+                <th ng-if="vm.config.actions">Actions:</th>
+              </tr>
+            </thead>
+            <tbody ng-if="vm.config.filter == 'field'">
+              <tr>
+                <td ng-repeat="col in vm.columns">
+                  <input
+                    ng-if="col.type !== 'boolean' && col.type !== 'array' && col.type !== 'object' && col.type !== 'custom'"
+                    class="form-control"
+                    placeholder="Type to search by {{col.label}}"
+                    type="text"
+                    ng-model="vm.query[col.prop]"/>
+                  <select
+                    ng-if="col.type === 'boolean'"
+                    class="form-control"
+                    ng-model="vm.query[col.prop]">
+                    <option value="">-</option>
+                    <option value="true">True</option>
+                    <option value="false">False</option>
+                  </select>
+                </td>
+                <td ng-if="vm.config.actions"></td>
+              </tr>
+            </tbody>
+            <tbody>
+              <tr ng-repeat="item in vm.data | filter:vm.query:vm.comparator | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">
+                <td ng-repeat="col in vm.columns" xos-link-wrapper>
+                  <span ng-if="!col.type">{{item[col.prop]}}</span>
+                  <span ng-if="col.type === 'boolean'">
+                    <i class="glyphicon"
+                      ng-class="{'glyphicon-ok': item[col.prop], 'glyphicon-remove': !item[col.prop]}">
+                    </i>
+                  </span>
+                  <span ng-if="col.type === 'date'">
+                    {{item[col.prop] | date:'H:mm MMM d, yyyy'}}
+                  </span>
+                  <span ng-if="col.type === 'array'">
+                    {{item[col.prop] | arrayToList}}
+                  </span>
+                  <span ng-if="col.type === 'object'">
+                    <dl class="dl-horizontal">
+                      <span ng-repeat="(k,v) in item[col.prop]">
+                        <dt>{{k}}</dt>
+                        <dd>{{v}}</dd>
+                      </span>
+                    </dl>
+                  </span>
+                  <span ng-if="col.type === 'custom'">
+                    {{col.formatter(item)}}
+                  </span>
+                  <span ng-if="col.type === 'icon'">
+                    <i class="glyphicon glyphicon-{{col.formatter(item)}}">
+                    </i>
+                  </span>
+                </td>
+                <td ng-if="vm.config.actions">
+                  <a href=""
+                    ng-repeat="action in vm.config.actions"
+                    ng-click="action.cb(item)"
+                    title="{{action.label}}">
+                    <i
+                      class="glyphicon glyphicon-{{action.icon}}"
+                      style="color: {{action.color}};"></i>
+                  </a>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+          <xos-pagination
+            ng-if="vm.config.pagination"
+            page-size="vm.config.pagination.pageSize"
+            total-elements="vm.data.length"
+            change="vm.goToPage">
+            </xos-pagination>
+        </div>
+        <div ng-show="(vm.data.length == 0 || !vm.data) && vm.loader == false">
+           <xos-alert config="{type: 'info'}">
+            No data to show.
+          </xos-alert>
+        </div>
+        <div ng-show="vm.loader == true">
+          <div class="loader"></div>
+        </div>
+      `,
+      bindToController: true,
+      controllerAs: 'vm',
+      controller: function(_, $scope, Comparator){
 
-          this.comparator = Comparator;
+        this.comparator = Comparator;
 
-          this.loader = true;
+        this.loader = true;
 
-          $scope.$watch(() => this.data, data => {
-            if(angular.isDefined(data)){
-              this.loader = false;
+        $scope.$watch(() => this.data, data => {
+          if(angular.isDefined(data)){
+            this.loader = false;
+          }
+        });
+
+        if(!this.config){
+          throw new Error('[xosTable] Please provide a configuration via the "config" attribute');
+        }
+
+        if(!this.config.columns){
+          throw new Error('[xosTable] Please provide a columns list in the configuration');
+        }
+
+        // handle default ordering
+        if(this.config.order && angular.isObject(this.config.order)){
+          this.reverse = this.config.order.reverse || false;
+          this.orderBy = this.config.order.field || 'id';
+        }
+
+        // if columns with type 'custom' are provided
+        // check that a custom formatte3 is provided too
+        let customCols = _.filter(this.config.columns, {type: 'custom'});
+        if(angular.isArray(customCols) && customCols.length > 0){
+          _.forEach(customCols, (col) => {
+            if(!col.formatter || !angular.isFunction(col.formatter)){
+              throw new Error('[xosTable] You have provided a custom field type, a formatter function should provided too.');
             }
-          });
+          })
+        }
 
-          if(!this.config){
-            throw new Error('[xosTable] Please provide a configuration via the "config" attribute');
-          }
+        // if columns with type 'icon' are provided
+        // check that a custom formatte3 is provided too
+        let iconCols = _.filter(this.config.columns, {type: 'icon'});
+        if(angular.isArray(iconCols) && iconCols.length > 0){
+          _.forEach(iconCols, (col) => {
+            if(!col.formatter || !angular.isFunction(col.formatter)){
+              throw new Error('[xosTable] You have provided an icon field type, a formatter function should provided too.');
+            }
+          })
+        }
 
-          if(!this.config.columns){
-            throw new Error('[xosTable] Please provide a columns list in the configuration');
-          }
+        // if a link property is passed,
+        // it should be a function
+        let linkedColumns = _.filter(this.config.columns, col => angular.isDefined(col.link));
+        if(angular.isArray(linkedColumns) && linkedColumns.length > 0){
+          _.forEach(linkedColumns, (col) => {
+            if(!angular.isFunction(col.link)){
+              throw new Error('[xosTable] The link property should be a function.');
+            }
+          })
+        }
 
-          // handle default ordering
-          if(this.config.order && angular.isObject(this.config.order)){
-            this.reverse = this.config.order.reverse || false;
-            this.orderBy = this.config.order.field || 'id';
-          }
+        this.columns = this.config.columns;
+        this.classes = this.config.classes || 'table table-striped table-bordered';
 
-          // if columns with type 'custom' are provided
-          // check that a custom formatte3 is provided too
-          let customCols = _.filter(this.config.columns, {type: 'custom'});
-          if(angular.isArray(customCols) && customCols.length > 0){
-            _.forEach(customCols, (col) => {
-              if(!col.formatter || !angular.isFunction(col.formatter)){
-                throw new Error('[xosTable] You have provided a custom field type, a formatter function should provided too.');
-              }
-            })
-          }
-
-          // if columns with type 'icon' are provided
-          // check that a custom formatte3 is provided too
-          let iconCols = _.filter(this.config.columns, {type: 'icon'});
-          if(angular.isArray(iconCols) && iconCols.length > 0){
-            _.forEach(iconCols, (col) => {
-              if(!col.formatter || !angular.isFunction(col.formatter)){
-                throw new Error('[xosTable] You have provided an icon field type, a formatter function should provided too.');
-              }
-            })
-          }
-
-          // if a link property is passed,
-          // it should be a function
-          let linkedColumns = _.filter(this.config.columns, col => angular.isDefined(col.link));
-          if(angular.isArray(linkedColumns) && linkedColumns.length > 0){
-            _.forEach(linkedColumns, (col) => {
-              if(!angular.isFunction(col.link)){
-                throw new Error('[xosTable] The link property should be a function.');
-              }
-            })
-          }
-
-          this.columns = this.config.columns;
-          this.classes = this.config.classes || 'table table-striped table-bordered';
-
-          if(this.config.actions){
-            // TODO validate action format
-          }
-          if(this.config.pagination){
-            this.currentPage = 0;
-            this.goToPage = (n) => {
-              this.currentPage = n;
-            };
-          }
-
+        if(this.config.actions){
+          // TODO validate action format
+        }
+        if(this.config.pagination){
+          this.currentPage = 0;
+          this.goToPage = (n) => {
+            this.currentPage = n;
+          };
         }
       }
     })
diff --git a/src/ui_components/dumbComponents/validation/validation.component.js b/src/ui_components/dumbComponents/validation/validation.component.js
index 91610e1..42deb4e 100644
--- a/src/ui_components/dumbComponents/validation/validation.component.js
+++ b/src/ui_components/dumbComponents/validation/validation.component.js
@@ -73,39 +73,37 @@
   </example>
     */
 
-  .directive('xosValidation', function(){
-    return {
-      restrict: 'E',
-      scope: {
-        field: '=',
-        form: '='
-      },
-      template: `
-        <div ng-cloak>
-          <xos-alert config="vm.config" show="vm.field.$error.required !== undefined && vm.field.$error.required !== false  && (vm.field.$touched || vm.form.$submitted)">
-            Field required
-          </xos-alert>
-          <xos-alert config="vm.config" show="vm.field.$error.email !== undefined && vm.field.$error.email !== false && (vm.field.$touched || vm.form.$submitted)">
-            This is not a valid email
-          </xos-alert>
-          <xos-alert config="vm.config" show="vm.field.$error.minlength !== undefined && vm.field.$error.minlength !== false && (vm.field.$touched || vm.form.$submitted)">
-            Too short
-          </xos-alert>
-          <xos-alert config="vm.config" show="vm.field.$error.maxlength !== undefined && vm.field.$error.maxlength !== false && (vm.field.$touched || vm.form.$submitted)">
-            Too long
-          </xos-alert>
-          <xos-alert config="vm.config" show="vm.field.$error.custom !== undefined && vm.field.$error.custom !== false && (vm.field.$touched || vm.form.$submitted)">
-            Field invalid
-          </xos-alert>
-        </div>
-      `,
-      transclude: true,
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: function(){
-        this.config = {
-          type: 'danger'
-        }
+  .component('xosValidation', {
+    restrict: 'E',
+    bindings: {
+      field: '=',
+      form: '='
+    },
+    template: `
+      <div ng-cloak>
+        <xos-alert config="vm.config" show="vm.field.$error.required !== undefined && vm.field.$error.required !== false  && (vm.field.$touched || vm.form.$submitted)">
+          Field required
+        </xos-alert>
+        <xos-alert config="vm.config" show="vm.field.$error.email !== undefined && vm.field.$error.email !== false && (vm.field.$touched || vm.form.$submitted)">
+          This is not a valid email
+        </xos-alert>
+        <xos-alert config="vm.config" show="vm.field.$error.minlength !== undefined && vm.field.$error.minlength !== false && (vm.field.$touched || vm.form.$submitted)">
+          Too short
+        </xos-alert>
+        <xos-alert config="vm.config" show="vm.field.$error.maxlength !== undefined && vm.field.$error.maxlength !== false && (vm.field.$touched || vm.form.$submitted)">
+          Too long
+        </xos-alert>
+        <xos-alert config="vm.config" show="vm.field.$error.custom !== undefined && vm.field.$error.custom !== false && (vm.field.$touched || vm.form.$submitted)">
+          Field invalid
+        </xos-alert>
+      </div>
+    `,
+    transclude: true,
+    bindToController: true,
+    controllerAs: 'vm',
+    controller: function(){
+      this.config = {
+        type: 'danger'
       }
     }
   })
diff --git a/src/ui_components/smartComponents/smartPie/smartPie.component.js b/src/ui_components/smartComponents/smartPie/smartPie.component.js
index f8a3985..2276b5d 100644
--- a/src/ui_components/smartComponents/smartPie/smartPie.component.js
+++ b/src/ui_components/smartComponents/smartPie/smartPie.component.js
@@ -172,77 +172,75 @@
       </file>
     </example>
     */
-  .directive('xosSmartPie', function(){
-    return {
-      restrict: 'E',
-      scope: {
-        config: '='
-      },
-      template: `
-        <canvas
-          class="chart chart-pie {{vm.config.classes}}"
-          chart-data="vm.data" chart-labels="vm.labels"
-          chart-legend="{{vm.config.legend}}">
-        </canvas>
-      `,
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: function($injector, $interval, $scope, $timeout, _){
+  .component('xosSmartPie', {
+    restrict: 'E',
+    bindings: {
+      config: '='
+    },
+    template: `
+      <canvas
+        class="chart chart-pie {{vm.config.classes}}"
+        chart-data="vm.data" chart-labels="vm.labels"
+        chart-legend="{{vm.config.legend}}">
+      </canvas>
+    `,
+    bindToController: true,
+    controllerAs: 'vm',
+    controller: function($injector, $interval, $scope, $timeout, _){
 
-        if(!this.config.resource && !this.config.data){
-          throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
-        }
-
-        const groupData = (data) => _.groupBy(data, this.config.groupBy);
-        const formatData = (data) => _.reduce(Object.keys(data), (list, group) => list.concat(data[group].length), []);
-        const formatLabels = (data) => angular.isFunction(this.config.labelFormatter) ? this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
-
-        const prepareData = (data) => {
-          // group data
-          let grouped = groupData(data);
-          this.data = formatData(grouped);
-          // create labels
-          this.labels = formatLabels(grouped);
-        }
-
-        if(this.config.resource){
-
-          this.Resource = $injector.get(this.config.resource);
-          const getData = () => {
-            this.Resource.query().$promise
-            .then((res) => {
-
-              if(!res[0]){
-                return;
-              }
-
-              prepareData(res);
-            });
-          }
-
-          getData();
-
-          if(this.config.poll){
-            $interval(() => {getData()}, this.config.poll * 1000)
-          }
-        }
-        else {
-          $scope.$watch(() => this.config.data, (data) => {
-            if(data){
-              prepareData(this.config.data);
-            }
-          }, true);
-        }
-
-        $scope.$on('create', function (event, chart) {
-          console.log(`create: ${chart.id}`);
-        });
-
-        $scope.$on('destroy', function (event, chart) {
-          console.log(`destroy: ${chart.id}`);
-        });
-
+      if(!this.config.resource && !this.config.data){
+        throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
       }
-    };
+
+      const groupData = (data) => _.groupBy(data, this.config.groupBy);
+      const formatData = (data) => _.reduce(Object.keys(data), (list, group) => list.concat(data[group].length), []);
+      const formatLabels = (data) => angular.isFunction(this.config.labelFormatter) ? this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
+
+      const prepareData = (data) => {
+        // group data
+        let grouped = groupData(data);
+        this.data = formatData(grouped);
+        // create labels
+        this.labels = formatLabels(grouped);
+      }
+
+      if(this.config.resource){
+
+        this.Resource = $injector.get(this.config.resource);
+        const getData = () => {
+          this.Resource.query().$promise
+          .then((res) => {
+
+            if(!res[0]){
+              return;
+            }
+
+            prepareData(res);
+          });
+        }
+
+        getData();
+
+        if(this.config.poll){
+          $interval(() => {getData()}, this.config.poll * 1000)
+        }
+      }
+      else {
+        $scope.$watch(() => this.config.data, (data) => {
+          if(data){
+            prepareData(this.config.data);
+          }
+        }, true);
+      }
+
+      $scope.$on('create', function (event, chart) {
+        console.log(`create: ${chart.id}`);
+      });
+
+      $scope.$on('destroy', function (event, chart) {
+        console.log(`destroy: ${chart.id}`);
+      });
+
+    }
   });
 })();
diff --git a/src/ui_components/smartComponents/smartTable/smartTable.component.js b/src/ui_components/smartComponents/smartTable/smartTable.component.js
index 622952f..1fbc9d0 100644
--- a/src/ui_components/smartComponents/smartTable/smartTable.component.js
+++ b/src/ui_components/smartComponents/smartTable/smartTable.component.js
@@ -78,10 +78,9 @@
     </example>
     */
    
-  .directive('xosSmartTable', function(){
-    return {
+  .component('xosSmartTable', {
       restrict: 'E',
-      scope: {
+      bindings: {
         config: '='
       },
       template: `
@@ -121,7 +120,7 @@
       bindToController: true,
       controllerAs: 'vm',
       controller: function($injector, LabelFormatter, _, XosFormHelpers){
-        
+
         // TODO
         // - Validate the config (what if resource does not exist?)
 
@@ -264,6 +263,5 @@
 
         getData();
       }
-    };
   });
 })();
\ No newline at end of file