define(['react', 'underscore'], function (React, _) {
  'use strict';

  var d      = React.DOM
    , div    = React.DOM.div
    , strong = React.DOM.strong
    , em     = React.DOM.em
    , h5     = React.DOM.h5
    , p      = React.DOM.p;

  var ListItem = React.createClass({

    displayName: 'ListItem',

    render: function () {
      var item = this.props.item;
      var view = this.props.view;
      var iconClass = this.props.selected ? 'fa-star' : 'fa-star-o';
      return div(
        {className: this.props.className},
        div(
          {onClick: this._select, className: 'thumbnail'},
          d.i({className: 'pointer pull-right fa ' + iconClass}),
          h5(null, strong({}, idents(item, view).join(' '))),
          p(null, line2(item, view)),
          p(null, em({}, subtext(item, view)))));
    },

    _select: function () {
      this.props.onChangeSelected(this.props.item[0], !this.props.selected);
    }

  });

  return ListItem;

  function idents (values, paths) {
    var i, l, v, p, idents = [];
    for (i = 1, l = values.length; i < l; i++) {
      v = values[i];
      p = paths[i];
      if (v) {
        if (!/primaryIdentifier$/.test(p)
            && !/\.(journal|volume|pages|pubMedId)$/.test(p)
            && !/organism\.[^\.]+$/.test(p)) {
          idents.push(v);
        }
      }
    }
    return _.unique(idents);
  }

  function line2 (values, paths) {
    var i, l, v, p, idents = [];
    for (i = 1, l = values.length; i < l; i++) {
      v = values[i];
      p = paths[i];
      if (v) {
        if (/primaryIdentifier$/.test(p)
            || /\.(journal|volume|pages|pubMedId)$/.test(p)) {
          idents.push(v);
        }
      }
    }
    return idents.join(' ');
  }


  function subtext (values, paths) {
    var i, l, v, p, idents = [];
    for (i = 1, l = values.length; i < l; i++) {
      v = values[i];
      p = paths[i];
      if (v && (/organism\.[^\.]+$/.test(p))) {
        idents.push(v);
      }
    }
    return idents.join(' ');
  }

  function bool (x) {
    return !!x;
  }
});

@@ -22,16 +22,37 @@
 erscore'
+, './grid-formatters'
 %5D, funct
@@ -64,16 +64,28 @@
 React, _
+, formatters
 ) %7B%0A  'u
@@ -358,24 +358,36 @@
 nction () %7B%0A
+      try %7B%0A
       var it
@@ -442,16 +442,371 @@
 s.view;%0A
+      var content, formatter;%0A      if (formatter = formatters%5Bthis.props.type%5D) %7B%0A        content = formatter(this.props);%0A      %7D else %7B%0A        content = %5B%0A          h5(%7Bkey: 'header'%7D, strong(%7B%7D, idents(item, view).join(' '))),%0A          p(%7Bkey: 'text'%7D, line2(item, view)),%0A          p(%7Bkey: 'note'%7D, em(%7B%7D, subtext(item, view)))%0A        %5D;%0A      %7D%0A%0A
       va
@@ -1079,147 +1079,140 @@
     
-h5(null, strong(%7B%7D, idents(item, view).join(' '))),%0A          p(null, line2(item, view)),%0A          p(null, em(%7B%7D, subtext(item, view)))));
+content));%0A      %7D catch (e) %7B%0A        console.error(e);%0A        return d.div(%7BclassName: 'alert alert-danger'%7D, String(e));%0A      %7D
 %0A   

Use configured formatter where available.