onClick JavaScriptボタンをできるだけコピペでLEXに移行する【リストボタン編】

先日、詳細画面のカスタムボタンについて同じ記事を書きました。

[Ajax Toolkitを使用したonClick JavaScriptボタンをできるだけコピペでLEXに移行する - Qiita](https://qiita.com/atskimura/items/efd0163531d9a1c2ff2a)

今度はリストビューのカスタムボタンについて考えてみましょう。

例としてSalesforceのヘルプにあるサンプル「[一括削除を実行するためのカスタムボタンの作成](https://help.salesforce.com/articleView?id=links_useful_custom_buttons_mass_delete.htm&type=5)」を移行してみましょう。
よくあるリストビューでチェックしたレコードを一括削除するボタンです。

## 元のボタン

マニュアルのサンプルのインデントをきれいにして、取引先の一括削除に変更しています。

```js
{!REQUIRESCRIPT("/soap/ajax/44.0/connection.js")} 

var records = {!GETRECORDIDS( $ObjectType.Account )}; 


if (records[0] == null) { 
  alert("Please select at least one record.")
} else { 
  var errors = []; 
  var result = sforce.connection.deleteIds(records); 
  if (result && result.length) { 
    var numFailed = 0; 
    var numSucceeded = 0; 
    for (var i = 0; i < result.length; i++) { 
      var res = result[i]; 
      if (res && res.success == 'true'){ 
        numSucceeded++; 
      } else { 
        var es = res.getArray("errors"); 
        if (es.length > 0) { 
          errors.push(es[0].message); 
        } 
        numFailed++; 
      } 
    } 
    if (numFailed > 0){ 
      alert("Failed: " + numFailed + "\nSucceeded: " + numSucceeded + " \n Due to: " + errors.join("\n")); 
    } else { 
      alert("Number of records deleted: " + numSucceeded); 
    } 
  } 
  window.location.reload(); 
}
```

## LEXに移行

前とほぼ同じで、以下のようなテンプレVisualforceにJavaScriptのコードをコピペします。
詳細画面のボタンと違って`recordSetvar`を設定しています。

```html
<apex:page standardController="Account" recordSetvar="accounts" sidebar="false" tabStyle="Account">
    <script type="text/javascript">
    var __sfdcSessionId = '{!GETSESSIONID()}';
    </script>
    <script src="../../soap/ajax/44.0/connection.js" type="text/javascript"></script>
    <script src="../../soap/ajax/44.0/apex.js" type="text/javascript"></script>
    <script type="text/javascript">
// ここに元のボタンのJavaScriptのコード
    </script>
</apex:page>
```

ただし、一部そのままでは動かないので、修正します。

### `GETRECORDIDS`のところ

```js
var records = {!GETRECORDIDS( $ObjectType.Account )}; 
```

は、以下に変更します。

```js
var records = "<apex:repeat value="{!selected}" var="a">{!a.Id},</apex:repeat>".slice(0,-1).split(',');
```

選択したレコードは`{!selected}`で取れます。
とりあえず適当に動くようにしていますが、Apexで文字列作った方が安全かとは思います。

### `window.location.reload()`のところ

```js
window.location.reload(); 
```

は、以下に変更します。

```js
history.back();
```

Visualforceページに遷移しちゃうのでリストビュー画面に戻しています。

### 完成したVisualforceページ

こうなります。

```html
<apex:page standardController="Account" recordSetvar="accounts" sidebar="false" tabStyle="Account">
    <script type="text/javascript">
    var __sfdcSessionId = '{!GETSESSIONID()}';
    </script>
    <script src="../../soap/ajax/44.0/connection.js" type="text/javascript"></script>
    <script src="../../soap/ajax/44.0/apex.js" type="text/javascript"></script>
    <script type="text/javascript">
var records = "<apex:repeat value="{!selected}" var="a">{!a.Id},</apex:repeat>".slice(0,-1).split(',');

if (records[0] == null) { 
  alert("Please select at least one record.")
} else { 
  var errors = []; 
  var result = sforce.connection.deleteIds(records); 
  if (result && result.length) { 
    var numFailed = 0; 
    var numSucceeded = 0; 
    for (var i = 0; i < result.length; i++) { 
      var res = result[i]; 
      if (res && res.success == 'true'){ 
        numSucceeded++; 
      } else { 
        var es = res.getArray("errors"); 
        if (es.length > 0) { 
          errors.push(es[0].message); 
        } 
        numFailed++; 
      } 
    } 
    if (numFailed > 0){ 
      alert("Failed: " + numFailed + "\nSucceeded: " + numSucceeded + " \n Due to: " + errors.join("\n")); 
    } else { 
      alert("Number of records deleted: " + numSucceeded); 
    } 
  } 
  history.back();
}
    </script>
</apex:page>
```

### ボタンの設定

ボタンの設定はこんな感じ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/27267/7bb0577c-7cc0-3870-3c6b-f28d4d196563.png)

## 動作例

こんな感じに動く。

![massdeletelex.gif](https://qiita-image-store.s3.amazonaws.com/0/27267/61ab29ac-8037-7827-d2e6-4be92feea9cc.gif)

# 終わりに

でも、移行できるものはLightningリストビューアクションに移行した方がいいと思いますよ。