
# Rollback

When first importing a dataset using the loadData() function, etc., or at a specific point in time (savePoint) after the dataset is changed, a complete copy of the dataset stored in the DataProvider is saved separately and the DataProvider is later restored (rollback) with these values. You can do it.

#### Data restoration function

The [rollback](/refs/Class/DataProviderBase#rollback) function restores the DataProvider using the data copy saved with [savePoint](/refs/Class/DataProviderBase#savepoint).
When data is restored to a specified `savePoint`, subsequent DataProvider savePoints will be deleted.
The initially replicated dataset can be restored using rollBack, but cannot be deleted, so it is deleted using DataProvider [clearSavePoints](/refs/Class/DataProviderBase#clearsavepoints).
If `savePoint` is not specified, it will be restored to the original replication.

```js
const fields = [
  { fieldName: 'KorName', dataType: 'text' },
  { fieldName: 'Gender', dataType: 'text' },
  { fieldName: 'Age', dataType: 'number' },
  { fieldName: 'Phone', dataType: 'text' },
  { fieldName: 'ProductId', dataType: 'text' },
  { fieldName: 'KorCountry', dataType: 'text' },
  { fieldName: 'OrderDate', dataType: 'datetime', datetimeFormat: 'yyyy-MM-dd', amText: 'AM', pmText: 'PM' },
  { fieldName: 'CardNumber', dataType: 'text' },
  { fieldName: 'Monetary', dataType: 'text' },
  { fieldName: 'StartDate', dataType: 'datetime', datetimeFormat: 'yyyy-MM-dd', amText: 'AM', pmText: 'PM' },
  { fieldName: 'EndDate', dataType: 'datetime', datetimeFormat: 'yyyy-MM-dd', amText: 'AM', pmText: 'PM' },
  { fieldName: 'ToMonth', dataType: 'number' },
  { fieldName: 'Month', dataType: 'number' },
  { fieldName: 'Year', dataType: 'number' },
  { fieldName: 'InterestRate', dataType: 'number' },
  { fieldName: 'SaveCost', dataType: 'number' },
  { fieldName: 'SaveMaturity', dataType: 'number' },
  { fieldName: 'CurrentSave', dataType: 'number' }
];

const columns = [
  { name: 'KorName', fieldName: 'KorName', width: '60', header: { text: 'Name' } },
  { name: 'Gender', fieldName: 'Gender', width: '40', header: { text: 'Gender' } },
  { name: 'Age', fieldName: 'Age', width: '40', header: { text: 'Age' }, styleName: 'right-column' },
  { name: 'Phone', fieldName: 'Phone', width: '100', header: { text: 'Phone' } },
  { name: 'ProductId', fieldName: 'ProductId', width: '120', header: { text: 'Product ID' } },
  { name: 'KorCountry', fieldName: 'KorCountry', width: '100', header: { text: 'Investment Country' } },
  { name: 'OrderDate', fieldName: 'OrderDate', width: '100', header: { text: 'Order Date' } },
  { name: 'CardNumber', fieldName: 'CardNumber', width: '140', header: { text: 'Card Number' } },
  { name: 'Monetary', fieldName: 'Monetary', width: '40', header: { text: 'Currency' } },
  { name: 'StartDate', fieldName: 'StartDate', width: '100', header: { text: 'First Payment Date' } },
  { name: 'EndDate', fieldName: 'EndDate', width: '100', header: { text: 'End Date' } },
  { name: 'ToMonth', fieldName: 'ToMonth', width: '50', header: { text: 'Payment Count' }, styleName: 'right-column' },
  { name: 'Month', fieldName: 'Month', width: '50', header: { text: 'Remaining Count' }, styleName: 'right-column' },
  { name: 'InterestRate', fieldName: 'InterestRate', width: '50', numberFormat: '0.00', header: { text: 'Interest Rate' }, styleName: 'right-column' },
  { name: 'SaveCost', fieldName: 'SaveCost', width: '80', numberFormat: '#,##0', header: { text: 'Payment Amount' }, styleName: 'right-column' },
  { name: 'SaveMaturity', fieldName: 'SaveMaturity', width: '80', numberFormat: '#,##0', header: { text: 'Maturity Amount' }, styleName: 'right-column' },
  { name: 'CurrentSave', fieldName: 'CurrentSave', width: '80', numberFormat: '#,##0', header: { text: 'Current Balance' }, styleName: 'right-column' }
];

const { gridView, dataProvider } = RealGrid.createGrid("realgrid", {
  columns,
  header: {
    height: 40
  },
  display: {
    rowHeight: 36,
    emptyMessage: "No data to display."
  },
  edit: {
    insertable: true,
    appendable: true
  },
  footer: {
    height: 40
  },
  stateBar: {
    width: 16
  },
  onInitialized: (grid) => {
    fetch('/data/en/simple_data.json')
      .then(response => response.json())
      .then(data => {
        grid.getDataSource().setRows(data);
      });
  }
}, {
  fields
});

window.gridView = gridView;
window.dataProvider = dataProvider;

function refreshPoints() {
  const points = dataProvider.getSavePoints();
  const list = document.getElementById('listPoints');
  
  list.innerHTML = '';
  points.forEach((c) => {
    const option = document.createElement('option');
    option.value = c;
    option.text = 'savePoint_' + c;
    list.appendChild(option);
  });
}

function btnRollBack() {
  const point = document.getElementById('listPoints').value;
  gridView.cancel();
  dataProvider.rollback(point);
  refreshPoints();
}

function btnSavePoint() {
  gridView.cancel();
  const isCheckState = document.getElementById('chkStates').checked;
  dataProvider.savePoint(isCheckState);
  refreshPoints();
}

function btnClearPoints() {
  dataProvider.clearSavePoints();
  refreshPoints();
}
```

```js
//Create savePoint
dataProvider.savePoint(true);
//rollback
dataProvider.rollback(savePoint);
//savePoint initialization
dataProvider.clearSavePoints();
```

#### Restoring data

* Restore DataProvider to a specific savePoint.
* All clones created after the specified savePoint are removed.
* Call clearSavePoints() to delete all replications, including the first replication.

```js
//Create a restore point
$('#btnSavePoint').click(function() {
     gridView.cancel();
     dataProvider.savePoint($("#chkStates").is(":checked"));
     refreshPoints();
});

//Restore data
$('#btnRollBack').click(function() {
     var point = $("#listPoints").val();
 
     gridView.cancel();
     dataProvider.rollback(point); // If point is omitted, restore to original replication
     refreshPoints();
});
 
//savePoint initialization
$('#btnClearPoints').click(function() {
     dataProvider.clearSavePoints();
     refreshPoints();
});

function refreshPoints() {
     var points = dataProvider.getSavePoints();
     var list = $("#listPoints");
 
     list.empty();
     $.map(points, function (c) {
         $("<option />", { value: c, text: "savePoint_" + c }).appendTo(list);
     });
}
```