# Theming

You can override pretty much all the HTML generated by ng-admin, at different levels.

## Stylesheet

Ng-admin CSS is composed of styles from [sb-admin](http://ironsummitmedia.github.io/startbootstrap-sb-admin-2/), on top of [Bootstrap 3](http://getbootstrap.com/). By using your own CSS in addition to the ng-admin CSS, you can customize the look and feel of every displayed component.

To ease styling, ng-admin adds custom classes for the entities and fields currently displayed, to allow a finer styling. For instance, the datagrid in the list view always uses a class named `ng-admin-entity-[entityName]`. In the datagrid also, each header in the table uses a class named `ng-admin-column-[fieldName]`, which should allow precise sizing of columns.

Don't hesitate to inspect the generated source to look for the right CSS selector.

## Custom Classes

To ease theming, you can add a custom class to your fields in every view, using the `cssClasses()` method.

```js
myEntity.listView().fields([
    nga.field('title').cssClasses(['foo', 'bar'])
]);
```

`cssClasses()` can optionally accept a function, to return a class depending on the current entry.

```js
myEntity.listView().fields([
    nga.field('title').cssClasses(function(entry) {
        if (entry && entry.values && entry.values.publishDate >= Date.now()) {
            return 'bg-success';
        }
    })
]);
```

The `listView` calls `cssClasses()` for each datagrid cell, and for the datagrid headers. There is no active 'entry' in headers, that's why you should always check that the `entry` parameter is defined in a `cssClasses` function.

## Customizing The Template For A Given Field

All field types support the `template()` method, which makes it easy to customize the look and feel of a particular field, without sacrificing the native features.

For instance, if you want to customize the appearance of a `NumberField` according to its value:

```js
listview.fields([
    nga.field('amount', 'number')
        .format('$0,000.00')
        .template('<span ng-class="{ \'red\': value < 0 }"><ma-number-column field="::field" value="::entry.values[field.name()]"></ma-number-column></span>')
]);
```

The template scope exposes the following variables:

* `value`, `field`, `entry`, `entity`, and `datastore` in `listView` and `showView`
* `value`, `field`, `values`, and `datastore` in filters
* `value`, `field`, `entry`, `entity`, `form`, and `datastore` in `editionView` and `creationView`

In `showView`, `editionView`, and `creationView`, the template zone covers only the field itself - not the label. To force the template to replace the entire line (including the label), pass `true` as second argument to the `template()` call. This can be very useful to conditionally hide a field according to a property of the entry:

```js
post.editionView()
    .fields([
        nga.field('category', 'choice')
            .choices([
                { label: 'Tech', value: 'tech' },
                { label: 'Lifestyle', value: 'lifestyle' }
            ]),
        nga.field('subcategory', 'choice')
            .choices(function(entry) {
                return subCategories.filter(function (c) {
                    return c.category === entry.values.category;
                });
            })
            // display subcategory only if there is a category
            .template('<ma-field ng-if="entry.values.category" field="::field" value="entry.values[field.name()]" entry="entry" entity="::entity" form="formController.form" datastore="::formController.dataStore"></ma-field>', true),
    ]);
```

Most of the time, `template()` is used to customize the existing ng-admin directives (like `ma-number-column>` in the previous example), for instance by decorating them. If you want to learn about these native directives, explore the [column](../src/javascripts/ng-admin/crud/column), [field](../src/javascripts/ng-admin/crud/field), and [fieldView](../src/javascripts/ng-admin/crud/fieldView) directories in ng-admin source.

## Customizing Directives Templates

Using Angular's [`$provide`](https://docs.angularjs.org/api/auto/service/$provide) service, and the ability to decorate another provider, you can customize the template of any directive used by ng-admin for your entire application. Here is an example of customization of the 'text' input field:

```js
var myApp = angular.module('myApp', ['ng-admin']);
myApp.config(function(NgAdminConfigurationProvider, $provide) {
        // Override textarea template
        $provide.decorator('maTextFieldDirective', ['$delegate', function ($delegate) {
            // You can modify directly the template
            $delegate[0].template = angular.element($delegate[0].template).addClass('MyClass')[0].outerHTML;

            // or use a templateURL (loaded from a file or a <script type="text/ng-template" id="string.html"></script> tag)
            $delegate[0].template = '';
            $delegate[0].templateUrl = 'string.html';

            return $delegate;
        }]);

        // ...
});
```

## Customizing The View Template For A Given Entity

For a given entity, each of the main views (`list`, `show`, `create`, `edit`, `delete`) can use a custom HTML template instead of the default one. Just pass it to the `template()` function on the view:

```js
var myTemplate = require('text!./path/to/list.html');
var myEntity = nga.entity('foo_endpoint');
myEntity.listView().template(myTemplate);
// continue myEntity configuration
// ...
var admin = nga.application('My Application');
admin.addEntity(myEntity);
```

## Customizing The View Templates For The Entire Application

You can use the `app.customTemplate()` method to customize the template of a given view across the entire application (for all entities). This method expects a function argument, which should return the template as a string.

```js
var myTemplate = require('text!./path/to/list.html');
var admin = nga.application('My Application');
admin.customTemplate(function(viewName) {
    if (viewName === 'ListView') {
        return myTemplate;
    }
})
```

## Customizing the Dashboard

If you want to use a custom template dashboard, you must [define a custom dashboard configuration](Dashboard.md). This will give you access to the `dashboard.template()` function:

```js
var myTemplate = require('text!./path/to/dashboard.html');
var admin = nga.application('My Application');
admin.dashboard(nga.dashboard()
    .template(mytemplate)
})
```

## Customizing the Application Header

If you want to override the application header (for instance to add authentication status on the top bar), use the `admin.header()` setter with a valid HTML content. Angular directives are executed in the context of the layout. For instance, to display a custom title and a right aligned link, use the following code:

```js
var customHeaderTemplate =
'<div class="navbar-header">' +
    '<a class="navbar-brand" href="#" ng-click="appController.displayHome()">' +
        My Custom Title
    '</a>' +
'</div>' +
'<p class="navbar-text navbar-right">' +
    '<a href="https://github.com/marmelab/ng-admin/blob/master/examples/blog/config.js">' +
        '<span class="glyphicon glyphicon-sunglasses"></span>&nbsp;View Source' +
    '</a>' +
'</p>';
var admin = nga.application('My Application');
admin.header(customHeaderTemplate);
```

## Customizing the Application Layout

If the header is not enough, and you need to override the entire application layout use the `admin.layout()` setter:

```js
var myLayout = require('text!./path/to/layout.html');
var admin = nga.application('My Application');
admin.layout(myLayout);
```

The original layout can be found in [src/javascripts/ng-admin/Main/view/layout.html](../src/javascripts/ng-admin/Main/view/layout.html).

## Customizing Error Messages

You can use the `app.errorMessage()`, `entity.errorMessage()` or `view.errorMessage()` methods to customize the message displayed when an error occurred with the API. These methods expect a function argument with the response as parameter, which should return the message as a string.

```js
entity.errorMessage(function (response) {
    return 'Global error: ' + response.status + '(' + response.data + ')';
});
```
## Customizing HTTP Error Messages

If you want to override, patch or extend the way HTTP errors are handled by the ng-admin [Http Error Service](../src/javascripts/ng-admin/Main/component/provider/HttpErrorService.js) then you may use an [Angular decorator](https://docs.angularjs.org/guide/decorators), as per the below example:

Create a decorator, HttpErrorDecorator.js

```js
// Change HTTP 403 error notification to display them as information
// and not errors ('humane-flatty-info' instead of 'humane-flatty-error')
export const HttpErrorDecorator = ($delegate, $translate, notification) => {
    $delegate.handle403Error = error => {
        $translate('STATE_FORBIDDEN_ERROR', {
            message: error.data.message,
        }).then(text => notification.log(text, {
            addnCls: 'humane-flatty-info',
        }));

        throw error;
    };

	return $delegate;
}

HttpErrorDecorator.$inject = ['$delegate', '$translate', 'notification'];

export default HttpErrorDecorator;

```

Bind the decorator to your application:

```js
myApp.decorator('HttpErrorService',require('HttpErrorDecorator'));
```
