動作環境
- Salesforce Lightningを使っている。
- SalesforceでVisualForceを使ったページである。
- カスタムコントローラを拡張したApexのクラスを利用したVisualForceのページでタイトルの問題が発生する。
問題の症状
- 保存のメソッド(ここではsaveメソッドを上書きしている)を実行したときに、1度目は問題ないが、2度目の保存を実行した際に、画面のリダイレクト後にVisualForceページでデータが表示されない。
- この際、リダイレクトをさせないようにすれば解決するが、どうしてもリダイレクトをさせいたい。
原因
- 結論を書くと、この原因はカスタムオブジェクトのIDがnullになっていることで、VisualForceページでデータが表示されないという、この記事のタイトルのトラブルが発生している。
前置き
- 以下、自分の考えた解決方法ですが、自分の作成した「カスタムコントローラを拡張したApexのクラス」特有の問題なのかもしれません。とりあえず、同じような症状で悩んでいるプログラマもいると思いますので、(及び、自分の備忘録のために)以下の解決方法を記録します。
- 検証のための全体コードは書きません。解決した方法は書いています。
うまく行かないコード その1
-
setRedirect(true)
を利用して、ただリダイレクトをさせるコードです。 - Web上で「カスタムコントローラを拡張したApexのクラス」などの記事を参考にしてコードを書くと、保存のメソッドは以下のようなコードになると思われます。
/*
* saveメソッドの上書き
*/
public PageReference save() {
this.stdController.save();
PageReference p = ApexPages.currentPage(); // ←これだと、2度目の保存ボタン(saveメソッド)のを実行した際に、データが表示されないという問題が発生する。
p.setRedirect(true);
return p;
}
- saveメソッドの2回目の実行時にエラーが起きる原因は、カスタムコントローラのオブジェクトのIDがnullになってしまうことです。(しかし、なぜnullになってしまうのかについては、よくわからない。)
- 1回目のリダイレクト時は、idはnullにならないので、うまくデータが表示されますが、2回目のリダイレクト時は、再びコンストラクタを通った際に、オブジェクトのIDがnullになってしまい、Visualforceのページのデータが表示されなくなってしまいます。そのため、次に以下の一行を追加してみます。
Id projectId = ApexPages.currentPage().getParameters().get('id');
うまく行かないコード その2
- 上記の1行を追加します。
/*
* saveメソッドの上書き
*/
public PageReference save() {
this.stdController.save();
PageReference p = ApexPages.currentPage();
Id projectId = ApexPages.currentPage().getParameters().get('id'); // 追加
p.getParameters().put('id', projectId);
p.setRedirect(true);
return p;
}
-
ApexPages.currentPage().getParameters().get('id')
でページのパラメータを取得すれば良いだろうと思ったが、やはりうまく行きません。 - そこで、以下のサイトを発見しました。
- このWebサイトに書かれているstdController.getId()を利用します。その結果、idがnullにならずに、うまく表示されてタイトルの問題が解決しました。
うまくいくコード
-
stdController.getId()
として、ページのIDパラメータを取得するのがポイントです。
/*
* saveメソッドの上書き
*/
public PageReference save() {
this.stdController.save();
PageReference p = ApexPages.currentPage();
p.getParameters().put(‘id’, this.stdController.getId()); // 修正
p.setRedirect(true);
return p;
}
- 言い換えると、
ApexPages.currentPage().getParameters().get('id')
では、idを取得出来ませんが、stdController.getId()
だとうまくidを取得できるという結論です。 - ついでに言うと、上記のコードでsaveなどのSOQLを更新する箇所はtry~catch文を使った方が良いですが、簡単に表示するために省略しております。
感想
- Salesforceにおいて、今後はVisualforceより、LWCを利用してコンテンツを作成するべきです。
- そのため、データベースの編集をする場合は、LWCでやった方が良いので、LWCで作成すれば、この問題に遭遇しないと思います。(つまり、VisualForceでデータを編集した場合、かつ、リダイレクトをして保存時に画面を更新させたい場合特有の問題です)
- しかし、印刷が必要な画面や、すでにVisualforceで作成された編集ページがある場合、「カスタムコントローラを拡張したApexのクラス」を利用することが考えられ、今後も今回の問題に遭遇してしまうプログラマが発生すると思われます。今回の記事は、そのような内容なので、ニッチなトラブルに関する記事ですが、Web上に中々、解決する方法のヒントが見つからなかったので、この記事を書きました。