旧Microsoft Edgeでhistory.backすると、チェックボックスやラジオボタンの値が消える問題を解決する方法

jQuery

Microsoft Edgeでお問い合わせフォーム等の、確認ページなどの遷移先からhistory.backで戻ってきたとき、チェックボックスやラジオボタンで選択した値が消えているという問題をご存知でしょうか?勝手にチェックが外れてしまうと再度選択し直さないといけなくなりユーザーはとても不便を感じることになりますよね?
この問題は2020年1月登場した「Chromium」ベースの新しいMicrosoft Edgeでは解消されましたが、旧ブラウザが段階的に更新され新しいものに置き換わるには少し時間がかかることも考えられますので、今回はそれまでの応急処置として、history.back等で戻ってきてもチェックボックスやラジオボタンの値が消えないようにする方法をご紹介します。
尚、今回紹介する方法を使うことで、Microsoft Edgeが新ブラウザに置き換わったときに問題が起きるといったことはないのでご安心ください。

旧Microsoft Edgeで起こるラジオボタンとチェックボックスの問題について

本題に入る前に旧Microsoft Edgeで起こるこの問題について簡単に説明しておきます。
まずは、サンプルを用意しました。

これは、チェックボックスの選択とラジオボタンの選択を含むフォームのサンプルモデルです。実際に動きを確認できるようにしました。これを旧Microsoft Edgeで確認するとわかりやすいのですが、チェックボックスやラジオボタンにチェックをいれた状態で「確認」ボタンでページ遷移し、遷移先の「前のページへ戻る」ボタン(history.back();)で戻ってきたときチェックしてあったものが消えるという現象が発生します。通常であればここに入力された値は維持されるべきなのですが、それがされないのは旧Microsoft Edgeがもつバグといれるかもしれません。
history.backでチェックボックスやラジオボタンのチェックが外れてしまうと、「確認画面から戻るたびにユーザーに再度チェックをし直してもらわないといけない」、「必須でない場合はチェックが外れていることにユーザーが気づかずそのまま処理されてしまうことがある」、といった問題が発生することがあるので対策を検討しなければなりません。

jQueryを使ってラジオボタンとチェックボックスの問題に対応する方法

この問題を解決する方法として今回は「jQuery」を使用します。ですので、はじめにまず「jQuery」を読み込んでおきます。

<script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

サンプルは、サーバー上に公開されたバージョン3.4.1を呼び出したものですが、もちろんバージョンが違っても、「jQuery」をダウンロードして使っても大丈夫です。

まずこの対策方法を簡単にご紹介します。今回問題になっているのはチェックボックスやラジオボタンの値がhistory.back時に保持されていいないことですが、それ以外のフィールドの値については保持されます。そこで、input type=”hidden”で隠しフィールドを用意してそこにチェックボックスやラジオボタンの値を保持させておき、history.back時はこの隠しフィールドに保持されていたデータをチェックボックスやラジオボタンの値として反映させるという方法でこの問題に対処します。それでは次のhtmlサンプルをご確認ください。

<form>

<div>
<input type="checkbox" name="checkbox1" value="チェック1" data-checkbox="check1"> チェック1
<input type="checkbox" name="checkbox1" value="チェック2" data-checkbox="check2"> チェック2
<input type="checkbox" name="checkbox1" value="チェック3" data-checkbox="check3"> チェック3
</div>

<div>
<input type="radio" name="radio2" value="ラジオ1" checked> ラジオ1
<input type="radio" name="radio2" value="ラジオ2"> ラジオ2
<input type="radio" name="radio2" value="ラジオ3"> ラジオ3
</div>

<input type="hidden" data-name="check1">
<input type="hidden" data-name="check2">
<input type="hidden" data-name="check3">
<input type="hidden" data-name="radiot2">

<input type="submit" value="確認">

</form>

隠しフィールド(input type=”hidden”)とチェックボックスやラジオボタンを結びつける方法として、隠しフィールドにdata属性(data-name=”~”)を設定しラジオボタンはname属性を入れています。チェックボックスは複数選択された際、隠しフィールド(input type=”hidden”)に配列で値を持たせることが難しいのでdata属性(data-checkbox=”~”)を個別に設定してそれぞれの隠しフィールド(input type=”hidden”)に値を持たせています。チェックボックスやラジオボタンにチェックが入るとdata属性が対応している隠しフィールドのvalue値に反映されるようにします。ラジオボタンはグループ毎に一つ、チェックボックスはチェックボックスの数分対応する隠しフィールドを設置する必要があります。
これを実際機能するようにするコードが下記になります。

$(function () {
    var $checkboxButton = $('input[type=checkbox]');
    var $radioButton = $('input[type=radio]');
    var $dataSaveField = $('[data-name]');

    //各ラジオボタンの設定(value値記録)
    $radioButton.on('change', function (e) {
        var $self = $(this);
       if ( $self.prop('checked')){
        var valueData = $self.val();
		}else{
		var valueData = '';
		}
        var nameData = $self.attr('name');
        var $myDataSaveField = $('[data-name=' + nameData + ']');
        $myDataSaveField.val(valueData);
		
    });
    //各チェックボックスの設定(value値記録)
    $checkboxButton.on('change', function (e) {
        var $self = $(this);
		if ( $self.prop('checked')){
        var valueData = $self.val();
		}else{
		var valueData = '';
		}
        var nameData = $self.attr('data-checkbox');
        var $myDataSaveField = $('[data-name=' + nameData + ']');
		$myDataSaveField.val(valueData); 
    });

    //隠しフィールドの値を渡す
    $dataSaveField.each(function () {
        var $self = $(this);
        var valueData = $self.val();
		 //各ラジオボタンへ値を渡す
        if(valueData === '') {}else{
        var nameData = $self.attr('data-name');
        var $groupButton = $('input[name=' + nameData + ']');
        $groupButton.each(function () {
            var $self = $(this);
            if ($self.val() === valueData) {
                $self.prop('checked', true);
            }
        });
    }
	   //各チェックボックスへ値を渡す
	    if(valueData === '') {}else{
        var nameData = $self.attr('data-name');
        var $groupButton = $('input[data-checkbox=' + nameData + ']');
        $groupButton.each(function () {
            var $self = $(this);
            if ($self.val() === valueData) {
                $self.prop('checked', true);
            }
        });
    }
    });

});

「//各ラジオボタンの設定」及び「//各チェックボックスボタンの設定」でチェックが入ったときそれぞれの隠しフィールドに値を渡す。「//隠しフィールドから値を取得」でhistorybackしたときに隠しフィールドから値をチェッボックスやラジオボタンに渡すといったことをしています。

ユーザーエージェントで旧Microsoft Edgeのみに効果を限定する

今回のチェッボックスやラジオボタンの対策が他のブラウザーに影響を与えることはないと考えていますが、もしかしたらなにか問題が発生する可能性もあります。今回の対策は旧Microsoft Edgeにのみ効果があればいいだけですのでこういった場合はユーザーエージェントでブラウザーを判別し、「旧Microsoft Edgeに効果がある」設定にしてあげるのがベターです。
旧Microsoft Edgeのユーザーエージェント判別は下記のように設定できます。

var userAgent = window.navigator.userAgent.toLowerCase();
if(userAgent.indexOf('edge') != -1) {
// Microsoft Edgeに対応する設定を記述
}

先ほどのチェッボックスやラジオボタンに対応するコードと組合せると次のようになります。

var userAgent = window.navigator.userAgent.toLowerCase();
if(userAgent.indexOf('edge') != -1) {

$(function () {
    var $checkboxButton = $('input[type=checkbox]');
    var $radioButton = $('input[type=radio]');
    var $dataSaveField = $('[data-name]');

    //各ラジオボタンの設定(value値記録)
    $radioButton.on('change', function (e) {
        var $self = $(this);
       if ( $self.prop('checked')){
        var valueData = $self.val();
		}else{
		var valueData = '';
		}
        var nameData = $self.attr('name');
        var $myDataSaveField = $('[data-name=' + nameData + ']');
        $myDataSaveField.val(valueData);
		
    });
    //各チェックボックスの設定(value値記録)
    $checkboxButton.on('change', function (e) {
        var $self = $(this);
		if ( $self.prop('checked')){
        var valueData = $self.val();
		}else{
		var valueData = '';
		}
        var nameData = $self.attr('data-checkbox');
        var $myDataSaveField = $('[data-name=' + nameData + ']');
		$myDataSaveField.val(valueData); 
    });

    //隠しフィールドの値を渡す
    $dataSaveField.each(function () {
        var $self = $(this);
        var valueData = $self.val();
		 //各ラジオボタンへ値を渡す
        if(valueData === '') {}else{
        var nameData = $self.attr('data-name');
        var $groupButton = $('input[name=' + nameData + ']');
        $groupButton.each(function () {
            var $self = $(this);
            if ($self.val() === valueData) {
                $self.prop('checked', true);
            }
        });
    }
	   //各チェックボックスへ値を渡す
	    if(valueData === '') {}else{
        var nameData = $self.attr('data-name');
        var $groupButton = $('input[data-checkbox=' + nameData + ']');
        $groupButton.each(function () {
            var $self = $(this);
            if ($self.val() === valueData) {
                $self.prop('checked', true);
            }
        });
    }
    });

});
}

最後に一番最初に示したサンプルに今回の対策を適応したものを置いておきます。旧Microsoft Edgeで確認し、比較してもらうと対策の効果があることをご確認いただけると思います。