title: sorting a datagrid with GWT
body: <p>I have a datagrid in GWT, and I'm using RPC to populate it with data, I can get the data to show up just fine, and I can also select individual cells but when it comes to sorting it just doesn't work! I can occasionaly click on column headers (it happens intermittently and I'm not sure why) but when I do nothing sorts. I'm using a dataProvider, but I think I'm implementing it incorrectly, I've attached the related code, can someone give me a pointer on how to do this correctly?</p>
  
  <p>first is the actual table itself</p>
  
  <pre><code>public class GuiInventory {
  
  public final static LayoutPanel hpMain = new LayoutPanel();
  
  static ListHandler&lt;OpInventory&gt; sortHandler;
  /*
  * Define a key provider for a Contact. We use the unique ID as the key,
  * which allows to maintain selection even if the name changes.
  */
  static ProvidesKey&lt;OpInventory&gt; keyProvider = new ProvidesKey&lt;OpInventory&gt;() {
      @Override
      public Object getKey(OpInventory item) {
          // Always do a null check.
          return (item == null) ? null : item.getPartID();
      }
  };
  
  //the table
  final static DataGrid&lt;OpInventory&gt; table = new DataGrid&lt;OpInventory&gt;(keyProvider);
  
  final static SelectionModel&lt;OpInventory&gt; selectionModel = new MultiSelectionModel&lt;OpInventory&gt;(keyProvider);
  
  /**
   * The provider that holds the list of contacts in the database.
   */
  private final static ListDataProvider&lt;OpInventory&gt; dataProvider = new ListDataProvider&lt;OpInventory&gt;();
  
  public ListDataProvider&lt;OpInventory&gt; getDataProvider() {
      return dataProvider;
  }
  
  /**
   * Add a display to the database. The current range of interest of the display
   * will be populated with data.
   * 
   * @param display a {@Link HasData}.
   */
  public void addDataDisplay(HasData&lt;OpInventory&gt; display) {
      dataProvider.addDataDisplay(display);
  }
  
  /**
   * Refresh all displays.
   */
  public void refreshDisplays() {
      dataProvider.refresh();
  }
  
  public static Widget init() {
  
      hpMain.clear();
      table.setWidth("100%");
      table.setSelectionModel(selectionModel);
      Ioma.dataservice.getPartInventory(new AsyncCallback&lt;ArrayList&lt;OpInventory&gt;&gt;() {
          @Override
          public void onFailure(Throwable caught) {
              // TODO Auto-generated method stub
          }
  
          @Override
          public void onSuccess(ArrayList&lt;OpInventory&gt; result) {              
              dataProvider.setList(result);
              // Attach a column sort handler to the ListDataProvider to sort the list.
              sortHandler = new ListHandler&lt;OpInventory&gt;(result);
              table.addColumnSortHandler(sortHandler);
              dataProvider.addDataDisplay(table);
  
              if (table.getColumnCount() == 0) {
                  initTable();
              }               
          }
      });
  
      //add in table
      hpMain.add(table);
      return hpMain;
  }
  
  public static void initTable() {
  
      // Add a text column to show the part ID.
      Column&lt;OpInventory, Number&gt; partIDColumn = new Column&lt;OpInventory, Number&gt;(new NumberCell()) {
          @Override
          public Integer getValue(OpInventory object) {
              return object.getPartID();
          }
      };
      table.addColumn(partIDColumn, "Part ID");
      table.setColumnWidth(partIDColumn, 4, Unit.PX);
  
      //add a sort to partID
      partIDColumn.setSortable(true);
      sortHandler.setComparator(partIDColumn, new Comparator&lt;OpInventory&gt;() {
          @Override
          public int compare(OpInventory o1, OpInventory o2) {
              return Integer.valueOf(o1.getPartID()).compareTo(o2.getPartID());
          }
      });
  
      // Add a text column to show the part Number.
      Column&lt;OpInventory, String&gt; partNumberColumn = new Column&lt;OpInventory, String&gt;(new EditTextCell()) {
          @Override
          public String getValue(OpInventory object) {
              return object.getPartNumber();
          }
      };
      table.addColumn(partNumberColumn, "Part Number");
      table.setColumnWidth(partNumberColumn, 4, Unit.PX);
  
      //add a sort to the part Number
      partNumberColumn.setSortable(true);
      sortHandler.setComparator(partNumberColumn, new Comparator&lt;OpInventory&gt;() {
          @Override
          public int compare(OpInventory o1, OpInventory o2) {
              return o1.getPartNumber().compareTo(o2.getPartNumber());
          }
      });
  
      //add a field updater to be notified when the user enters a new Part Number
      partNumberColumn.setFieldUpdater(new FieldUpdater&lt;OpInventory, String&gt;() {
          @Override
          public void update(int index, OpInventory object, String value) {
              object.setPartNumber(value);
              //TODO add async call to database to update part Number
              table.redraw();
          }
      });
  
      // Add a text column to show the name.
      Column&lt;OpInventory, String&gt; nameColumn = new Column&lt;OpInventory, String&gt;(new EditTextCell()) {
          @Override
          public String getValue(OpInventory object) {
              return object.getName();
          }
      };
      table.addColumn(nameColumn, "Name");
      table.setColumnWidth(nameColumn, 10, Unit.PX);
  
      //add a field updater to be notified when the user enters a new part name
      nameColumn.setFieldUpdater(new FieldUpdater&lt;OpInventory, String&gt;() {
          @Override
          public void update(int index, OpInventory object, String value) {
              object.setName(value);
              //TODO add async call to database to update part name
  
              table.redraw();
          }
      });
  
      //add a sort to the name
      nameColumn.setSortable(true);
      sortHandler.setComparator(nameColumn, new Comparator&lt;OpInventory&gt;() {
          @Override
          public int compare(OpInventory o1, OpInventory o2) {
              return o1.getName().compareTo(o2.getName());
          }
      });
  
  }
  </code></pre>
  
  <p>this is the Opinventory class to hold each object in the datagrid</p>
  
  <pre><code>public class OpInventory implements Comparable&lt;OpInventory&gt;, IsSerializable {
  
  int partID;
  String partNumber;
  String name;
  String desc;
  String partLotNumber;
  String supplier;
  String reOrderNumber;
  boolean isActive;
  int quantity;
  Double price;
  
  /**
  * The key provider that provides the unique ID of a contact.
  */
  public static final ProvidesKey&lt;OpInventory&gt; KEY_PROVIDER = new ProvidesKey&lt;OpInventory&gt;() {
      @Override
      public Object getKey(OpInventory item) {
          return item == null ? null : item.getPartID();
      }
  };
  
  @Override
  public int compareTo(OpInventory o) {
      return (o == null || o.partNumber == null) ? -1 : -o.partNumber.compareTo(partNumber);
  }
  
  @Override
  public boolean equals(Object o) {
      if (o instanceof OpInventory) {
          return partID == ((OpInventory) o).partID;
      }
      return false;
  }
  
  @Override
  public int hashCode() {
      return partID;
  }
  
  public OpInventory(int partID, String partNumber, String name, String desc, String partLotNumber, String supplier, String reOrderNumber, Double price, boolean isActive) {
      this.partID = partID;
      this.partNumber = partNumber;
      this.name = name;
      this.desc = desc;
      this.partLotNumber = partLotNumber;
      this.supplier = supplier;
      this.reOrderNumber = reOrderNumber;
      this.price = price;
      this.isActive = isActive;
  }
  
  public OpInventory() {
  
  }
  
  //getters and setters here
  </code></pre>
  
  <p>}</p>