質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • PHP

    21253questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • jQuery

    7084questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Laravel 5

    2060questions

    Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

  • jQuery UI

    167questions

    jQuery UI はjQuery公式のインターフェースライブラリであり、対話型のウェブアプリケーションを作る際に役立ちます。

jQuery UI Datepickerで動的に選択不可日を設定したい。

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 998

rock_square

score 5

  jQuery UI Datepickerで動的に選択不可日を設定したい。

 前提・実現したいこと

Laravel5.5を使って、システム開発を行っています。

日付を入力する箇所が2ヶ所あり(出発日時、到着日時)、それぞれに関して入力補助として jQuery UI Datepicker を使用してカレンダーを出すようにしています。
その際に、選択不可となる日付をサーバーから取得し、カレンダーに反映しています。

初期表示時にPHPで取得した配列($arr_list['unavailable_days'])の内容は

array:1 [
0 => "2018-06-19",
1 => "2018-06-24"
]

です。

こちらの値を用いて初期表示を行うと、2018/06/19 と 2018/06/24 がカレンダー上で選択不可状態で表示されます。
これが「正常にカレンダーに反映できた」という状態です。

初期表示させた後、出発空港または到着空港を変更した場合、初期表示の場合と同じくサーバーから選択不可となる日付を取得し、カレンダーに反映させたいと考えています。
初期表示は正常にカレンダーに反映できたのですが、変更時のカレンダー反映ができない状況にあります。

下記、表示を行っているHTMLと、処理を行っているJS部分となります。

<tr class="required">
    <th colspan="2">出発空港</th>
    <td class="form-group">
        <span class="lookup w30">
            <input class="form-control airport-dialog" name="departure_airport" type="text" value="">
            <input class="form-control" name="departure_airport_id" type="hidden" value="">
        </span>
    </td>
</tr>

<tr class="required">
    <th colspan="2">到着空港</th>
    <td class="form-group">
        <span class="lookup w30">
            <input class="form-control airport-dialog" name="arrival_airport" type="text" value="">
            <input class="form-control" name="arrival_airport_id" type="hidden" value="">
        </span>
    </td>
</tr>

<tr class="required">
    <th colspan="2">出発日時</th>
    <td class="form-group">
        <input id="departure_date" type="tel" name="departure_date" value="" class="form-control w30 rm10" style="width:250px;display:inline;" placeholder="yyyy/mm/dd" autocomplete="off" >
    </td>
</tr>

<tr class="required">
    <th colspan="2">到着日時</th>
    <td class="form-group">
        <input id="arrival_date" type="tel" name="arrival_date" value="" class="form-control w30 rm10" style="width:250px;display:inline;" placeholder="yyyy/mm/dd" autocomplete="off" >
    </td>
</tr>
<script>
//出発日時カレンダー初期表示
$(function () {
    var dateFormat = 'yyyy/mm/dd';
    var disableDates = [
        @foreach($arr_list['unavailable_days'] as $num => $days)
        <?php
          $days_ = str_replace('-','/',$days);
        ?>
        '{{$days_}}',
        @endforeach
     ];

    //出発日カレンダー指定
    $('#departure_date').datepicker({
        format: dateFormat,
        startDate: '+1d',
        endDate: '+30d',
        beforeShowDay : function(days) {
            var formatedDate = $.datepicker.formatDate('yy/mm/dd', days);
            return ( disableDates.indexOf(formatedDate) == -1 );
        }
    });
});

//到着日時カレンダー初期表示
$(function () {
    var dateFormat = 'yyyy/mm/dd';
    var disableDates = [
        @foreach($arr_list['unavailable_days'] as $num => $days)
        <?php
          $days_ = str_replace('-','/',$days);
        ?>
        '{{$days_}}',
        @endforeach
     ];

    //到着日カレンダー指定
    $('#arrival_date').datepicker({
        format: dateFormat,
        startDate: '+1d',
        endDate: '+30d',
        beforeShowDay : function(days) {
            var formatedDate = $.datepicker.formatDate('yy/mm/dd', days);
            return ( disableDates.indexOf(formatedDate) == -1 );
        }
    });
});


//変更時の処理
$(function() {
    //出発空港の変更検知
    $(document).on('blur', 'input[name=departure_airport]', function() {
        datetime();
    });

    //到着空港の変更検知
    $(document).on('blur', 'input[name=arrival_airport]', function() {
        datetime();
    });

    function datetime(){
        var departure_airport_id = document.form_main.departure_airport_id.value;
        var arrival_airport_id = document.form_main.arrival_airport_id.value;
        var token = '{{csrf_token()}}'

        //空港変更時
        if(departure_airport_id!="" && arrival_airport_id!=""){
            var dateFormat = 'yy/mm/dd';
            var send_url = '{{url('flight/unavail_days')}}';

            var formData = new FormData();
            formData.append('_token', token);
            formData.append('departure_airport_id', departure_airport_id);
            formData.append('arrival_airport_id', arrival_airport_id);

            $.ajax({
                type: 'POST',
                contentType: false,
                processData: false,
                url: send_url,
                data: formData,
                success: function(rdata) {
                    var disableDates = JSON.parse(rdata);

                    //カレンダー制御
                    $('#departure_date').datepicker('option','beforeShowDay',function(days){
                        var formatedDate = $.datepicker.formatDate(dateFormat, days);
                        return ( disableDates.indexOf(formatedDate) == -1 );
                    });

                    //カレンダー制御
                    $('#arrival_date').datepicker('option','beforeShowDay',function(days){
                        var formatedDate = $.datepicker.formatDate(dateFormat, days);
                        return ( disableDates.indexOf(formatedDate) == -1 );
                    });
                },
                error: function(data) {
                    //alert('エラーが発生しました。');
                },
            });
        }
    }
});
</script>


となっています。

 試したこと

Ajax直後での取得データと、カレンダー制御部分でコンソールへのログ出力を行いました。

                success: function(rdata) {
                    var disableDates = JSON.parse(rdata);
console.log('データ取得');
console.log(disableDates);
                    //カレンダー制御
                    $('#departure_date').datepicker('option','beforeShowDay',function(days){
console.log('選択不可');
console.log(days);
                        var formatedDate = $.datepicker.formatDate(dateFormat, days);
                        return ( disableDates.indexOf(formatedDate) == -1 );
                    });

Ajaxでのデータは

データ取得
edit:1535 (2) ["2018/06/19", "2018/06/24"]

という様に取得できているのですが、カレンダーへの反映部分がうまく動作していない様です。
⇒console.log('選択不可'); と console.log(days); が出力されない。

おそらく呼び出し方に問題があると思われますが、この状態からどの様に対応すれば良いかといった部分で詰まっています。

 補足情報(FW/ツールのバージョンなど)

◆動作環境
・Windows10 Pro 64bit
・Apache2.4
・PHP7.1
・Laravel5.5
・MySQL5.7
・jQuery UI Datepicker
⇒http://js.studio-kingdom.com/jqueryui/widgets/datepicker

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • rock_square

    2018/06/20 10:51

    コメントありがとうございます。再設定の方は $('#departure_date').datepicker('option','beforeShowDay',function(days){…} のループ自体が回らないんですよね。なので、return ( disableDates.indexOf(formatedDate) == -1 ); の部分までも辿り着けていない状況です。

    キャンセル

  • LineOfLightning

    2018/06/20 11:23

    問題の切り分けのために、念のために確認したいんですが、空港変更後、カレンダーを表示させても「選択不可」がコンソールに出力されないということで合ってますか? 空港変更しただけでは、「選択不可」は出力されないので念の為・・・

    キャンセル

  • rock_square

    2018/06/20 13:40

    コメントありがとうございます。そうですね。空港を変更し、カレンダーを表示させても選択不可日が更新されていなかった(選択した空港によって選択不可日が変わります)ので おかしいと思い、提示した場所へ「選択不可」がコンソールに出力されなかった…というのが経緯です。最終的に、カレンダーの選択不可日が選択された空港によって更新されれば良く、その過程で「選択不可」をコンソールに出力して確認した、という流れです。

    キャンセル

回答 1

0

jQuery-uiのdatepickerは、途中でオプションを変更しても反映されないようです。
なので、一旦、destroyしてから作り直すしかないみたいです。

こんな感じでどうでしょう?
動作確認はしていませんが・・・

// 外部変数として、デフォルトオプションを定義
var default_options = {format: dateFormat, startDate: '+1d', endDate: '+30d'};
success: function(rdata) {
  var disableDates = JSON.parse(rdata);
  console.log('データ取得');
  console.log(disableDates);
    //カレンダー制御
  $('#departure_date').datepicker('destroy');

  // デフォルトオプションをコピー
  let new_options = $.extend(true, {}, default_options);
  new_options.beforeShowDay = function(days){
      console.log('選択不可');
      console.log(days);
      var formatedDate = $.datepicker.formatDate(dateFormat, days);
      return ( disableDates.indexOf(formatedDate) == -1 );
  };

  $('#departure_date').datepicker(new_options);
  $('#departure_date').datepicker('refresh');

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/20 14:07

    ありがとうございます。
    ご提示いただいた内容で試してみたのですが、特に動作に変化はありませんでした(エラーも出ていない状況です)。

    キャンセル

  • 2018/06/20 18:10

    私が動作確認した限りでは、beforeShowDay の戻り値を初期の時、不可日変更の時、の両方を
    return [( disableDates.indexOf(formatedDate) == -1 ), "", ""];
    に直すだけで、他のコードは特に修正しなくても「選択不可日」の変更が反映されていましたよ!

    一度、datepickerを含むjquery_ui そのものを、新しくダウンロードして置き換えた方が良いのかもしれません・・(もし既存で問題なく動いている画面で、同じライブラリを使っているなら、この画面でだけ新しいjquery-uiを読み込むようにして確認するのでもいいと思います。)

    キャンセル

  • 2018/06/21 10:29

    確かに、jQuery UIのdatepickerの場合、作り直す必要はないみたいですね。すみません。bootstrap-datepickerと混同してました。後、動作確認したところ、一応、beforeShowDayの戻り値が配列ではない場合でも、動作するみたいです。(あまり、おすすめできる書き方ではないですが・・・)

    キャンセル

  • 2018/06/21 11:07

    それと、下記の部分で、括弧が一つ多いんですが、エラーになってませんか?開発者ツールのコンソールでエラーになっているか確認してますか?
    //空港変更時
    if(departure_airport_id!="" && arrival_airport_id!="")){

    キャンセル

  • 2018/06/21 15:39 編集

    mix-peachさん
    ご返信ありがとうございます。
    システム全体で共用している jquery-ui であるため、該当ページだけ分けて jquery-ui をダウンロードして差し替えたのですが、状況は変わりませんでした。
    どうやら、完全に環境に依存(他に読み込んでいるモジュールか、Laravelあたり?)している様なので、もう少しこちらで原因となるポイントを切り分けて考えてみたいと思います。
    ありがとうございました。

    LineOfLightningさん
    > 括弧が一つ多いんですが、エラーになってませんか?開発者ツールのコンソールでエラーになっているか確認してますか?

    すいません。こちら単純なソースのコピペミスですね。
    実際のソースは、エラーが出ていないことは確認済です。
    記載内容を修正しておきます。
    ご指摘ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • PHP

    21253questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • jQuery

    7084questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Laravel 5

    2060questions

    Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

  • jQuery UI

    167questions

    jQuery UI はjQuery公式のインターフェースライブラリであり、対話型のウェブアプリケーションを作る際に役立ちます。