web-dev-qa-db-ja.com

複数のAngular UI Bootstrap Datepickerを単一の形式で使用するには?

さまざまなことに2つ以上の日付フィールドを使用する必要があるフォームがあります。 Angular UI Bootstrapこれは、フォームに日付フィールドが1つしかない場合に正常に動作します。しかし、複数の日付フィールドがあり、これを機能させる簡単な方法を知らないでください。

これは私のHTMLサンプルです。

_ <label>First Date</label>  
    <div class="input-group">
     <input type="text" class="form-control" datepicker-popup="{{format}}" name="dt" ng-model="formData.dt" is-open="opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
      <span class="input-group-btn">
        <button class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
      </span>
    </div>      

 <label>Second Date</label>  
    <div class="input-group">
     <input type="text" class="form-control" datepicker-popup="{{format}}" name="dtSecond" ng-model="formData.dtSecond" is-open="opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
      <span class="input-group-btn">
        <button class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
      </span>
    </div>     
_

私のJSは:

_myApp.controller('DatePickrCntrl', function ($scope) {

      $scope.today = function() {
        $scope.formData.dt = new Date();
      };
      $scope.today();

      $scope.showWeeks = true;
      $scope.toggleWeeks = function () {
        $scope.showWeeks = ! $scope.showWeeks;
      };

      $scope.clear = function () {
        $scope.dt = null;
      };

      // Disable weekend selection
      $scope.disabled = function(date, mode) {
        return ( mode === 'day' && ( date.getDay() === 0 || date.getDay() === 6 ) );
      };

      $scope.toggleMin = function() {
        $scope.minDate = ( $scope.minDate ) ? null : new Date();
      };
      $scope.toggleMin();

      $scope.open = function($event) {
        $event.preventDefault();
        $event.stopPropagation();

        $scope.opened = true;
      };

      $scope.dateOptions = {
        'year-format': "'yy'",
        'starting-day': 1
      };

      $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'shortDate'];
      $scope.format = $scope.formats[0];

});
_

サンプル here に基づいて実装しました。ここにある問題は次のとおりです。

1)日付フィールドのいずれかをクリックすると、ポップアップ日付ピッカーが台無しになり、1に2つの日付ピッカーが表示されるようです。

2)_is-open="opened"_属性を削除すると、ポップアップウィンドウが正常に機能するように見えます。ただし、_is-open="opened"_がないと、ボタンのng-click="open($event)は機能しません。

3)各日付フィールドには異なるngモデルがあるため、_ng-model="formData.dt"_を含む最初の日付フィールドを除くすべての日付フィールドにデフォルトの日付を設定することはできません

これを解決する唯一の長い方法は、日付フィールドごとにコントローラを分離することです

Angular UI Bootstrapを使用する場合、他の人が1つのフォーム自体に複数の日付フィールドを実装する方法を知りたいです。

24
Neel

私は1つのフォームに30のコントローラーを持っていますが、問題ありません。 ng-repeatで必要な場合は、同じ概念を使用してください。

 <label>First Date</label>  
    <div class="input-group">
     <input type="text" class="form-control" datepicker-popup="{{format}}" 
            name="dt" ng-model="formData.dt" is-open="datepickers.dt" 
            datepicker-options="dateOptions" ng-required="true" 
            close-text="Close" />
      <span class="input-group-btn">
        <button class="btn btn-default" ng-click="open($event,'dt')">
            <i class="glyphicon glyphicon-calendar"></i></button>
      </span>
    </div>      

 <label>Second Date</label>  
    <div class="input-group">
     <input type="text" class="form-control" datepicker-popup="{{format}}" 
            name="dtSecond" ng-model="formData.dtSecond" 
            is-open="datepickers.dtSecond" datepicker-options="dateOptions" 
            ng-required="true" close-text="Close" />
      <span class="input-group-btn">
        <button class="btn btn-default" ng-click="open($event,'dtSecond')">
            <i class="glyphicon glyphicon-calendar"></i></button>
      </span>
    </div>     

myApp.controller('DatePickrCntrl', function ($scope) {
      $scope.datepickers = {
        dt: false,
        dtSecond: false
      }
      $scope.today = function() {
        $scope.formData.dt = new Date();

        // ***** Q1  *****
        $scope.formData.dtSecond = new Date();
      };
      $scope.today();

      $scope.showWeeks = true;
      $scope.toggleWeeks = function () {
        $scope.showWeeks = ! $scope.showWeeks;
      };

      $scope.clear = function () {
        $scope.dt = null;
      };

      // Disable weekend selection
      $scope.disabled = function(date, mode) {
        return ( mode === 'day' && ( date.getDay() === 0 || date.getDay() === 6 ) );
      };

      $scope.toggleMin = function() {
        $scope.minDate = ( $scope.minDate ) ? null : new Date();
      };
      $scope.toggleMin();

      $scope.open = function($event, which) {
        $event.preventDefault();
        $event.stopPropagation();

        $scope.datepickers[which]= true;
      };

      $scope.dateOptions = {
        'year-format': "'yy'",
        'starting-day': 1
      };

      $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'shortDate'];
      $scope.format = $scope.formats[0];

});


 // ***** Q2 ***** somemodel can be just an array [1,2,3,4,5]
 <div ng-repeat="o in somemodel">
 <label>Date Label</label>  
    <div class="input-group">
     <input type="text" class="form-control" datepicker-popup="{{format}}"
            name="dt{{o}}" ng-model="datepickers.data[o]" 
            is-open="datepickers.isopen[o]" datepicker-options="datepickers.option" 
            ng-required="true" close-text="Close" />
      <span class="input-group-btn">
        <button class="btn btn-default" ng-click="open($event,o)">
            <i class="glyphicon glyphicon-calendar"></i></button>
      </span>
    </div>
  </div>


myApp.controller('DatePickrCntrl', function ($scope) {

      $scope.datepickers = {
        data: {},
        options: {
            'year-format': "'yy'",
            'starting-day': 1
        },
        isopen: {}
      }
      $http.get("get/data/for/some/model", function(result) {
         $scope.somemodel = result;
         for (var i = 0; i < result.length; i++) {
           $scope.datepickers.isopen[result] = false;
           $scope.datepickers.data[result] = new Date(); //set default date.
         }
      });

  // fill in rest of the function
});
42
wayne

よりシンプルなソリューション。 HTMLの改造のみが必要で、必要に応じてng-repeatで使用できます。開いたものに名前を付けるだけで創造的です

これをコントローラーに貼り付けます:

$scope.calendar = {
    opened: {},
    dateFormat: 'MM/dd/yyyy',
    dateOptions: {},
    open: function($event, which) {
        $event.preventDefault();
        $event.stopPropagation();
        $scope.calendar.opened[which] = true;
    } 
};

HTML:

<div class="form-group row">
    <div class="col-lg-6">
        <label for="formDOB">Date of Birth</label>
        <p class="input-group">
          <input type="text" class="form-control" datepicker-popup="{{calendar.dateFormat}}" ng-model="record.birthDate" is-open="calendar.opened.dob" datepicker-options="calendar.dateOptions" close-text="Close" placeholder="Date of Birth" />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="calendar.open($event, 'dob')"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>
    </div>
    <div class="col-lg-6">
        <label for="formWinDate">Win Date</label>
        <p class="input-group">
          <input type="text" class="form-control" datepicker-popup="{{calendar.dateFormat}}" ng-model="record.winDate" is-open="calendar.opened.win" datepicker-options="calendar.dateOptions" close-text="Close" placeholder="Win DAte" />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="calendar.open($event, 'win')"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>
    </div>
</div>
19
geilt

ウェイン の答えは素晴らしい。追加するのは、関数 'open()'を改善できることだけです。

_$scope.open = function ($event, datePicker) {
    $event.preventDefault();
    $event.stopPropagation();

    $scope.closeAll();
    datePicker.opened = true;
};
_

そして、あなたはそれをそのように使用しなければなりません:

_ng-click="open($event, dateFrom)"
_

どこで デートから ngモデルです(つまり、使用します $ scope.dateFrom)。

編集:$scope.closeAll();は、すべてのdatePickerを閉じる関数です。次のように書くことができます:

_$scope.closeAll = function() {
    $scope.dateFrom.opened = false;
    $scope.dateTo.opened = false;
};
_
5

NgモデルとUI情報を混在させたくないのですが、このためには、開始フラグを保存する配列を定義し、datePickerが開かれているかどうかを確認する必要があります。

さらに、ボタンでdatePickerをclosinfできるように、「開く」動作を「トグル」に変更しました。

ここに私のコントローラーがあります:

$scope.toggleOpenDatePicker = function($event,datePicker) {
   $event.preventDefault();
   $event.stopPropagation();
   $scope[datePicker] = !$scope[datePicker];
};

その後、次のように使用できます。

<input type="text" class="form-control" ng-model="model.date1" is-open="date1" />
   <span class="input-group-btn">
      <button type="button" class="btn btn-default" ng-click="toggleOpenDatePicker($event,'date1')"><i class="glyphicon glyphicon-calendar"></i>      
      </button>
   </span>

$ scopeのアイデアは here から借りたものです。

2
Toni Gamez

this plunker を少し変更することで問題を解決しました。

[〜#〜] html [〜#〜]

<div class="row">
    <div class="col-md-6">
        <p class="input-group">
          <input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="openDatePickers[0]" min-date="minDate" max-date="'2015-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="open($event, 0)"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>
    </div>
</div>
    <h4>Popup</h4>
<div class="row">
    <div class="col-md-6">
        <p class="input-group">
          <input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="openDatePickers[1]" min-date="minDate" max-date="'2015-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="open($event, 1)"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>
    </div>
</div>

およびコントローラー内

$scope.openDatePickers = [];
$scope.open = function ($event, datePickerIndex) {
   $event.preventDefault();
   $event.stopPropagation();

   if ($scope.openDatePickers[datePickerIndex] === true) {
      $scope.openDatePickers.length = 0;
   } else {
      $scope.openDatePickers.length = 0;
      $scope.openDatePickers[datePickerIndex] = true;
   }
};

私の変更

代わりに数字(0または1)を使用します$index in angular ng-repeat

このような:

is-open="openDatePickers[**$index**]"

ng-click="open($event, **$index**)"

<p class="input-group">
   <input type="text" class="form-control" datepicker-popup="{{format}}" ng-model="dt" is-open="openDatePickers[$index]" min-date="minDate" max-date="'2015-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close">
   <span class="input-group-btn">
      <button type="button" class="btn btn-default" ng-click="open($event, $index)"><i class="glyphicon glyphicon-calendar"></i></button>
   </span>
</p>

私は別の方法でそれを使用し、私には少し簡単に見えます。私は前述のアプローチのいずれかを使用していましたが、静的識別子を持たずにループを実行していたため、大量のカレンダーを作成するのが面倒でした。したがって、ng-repeat内に多数のカレンダーを作成したい場合、このソリューションはまさにあなたにとって有効です。それが役に立てば幸い!

それがコントローラーです

       $scope.datepickers = {
            data: {},
            isopen: {}
       }
       // setting the defaults once
       for (var i = 0; i < $scope.array.length; i++) {
            $scope.datepickers.isopen[i] = false;
            $scope.datepickers.data[i] = new Date();
        }

        // aso..

        $scope.valuationDatePickerOpen = function($event, index) {
          if ($event) {
            $event.preventDefault();
            $event.stopPropagation();
          }
          $scope.datepickers.isopen[index] = true;
        };

そして、これは私のループ内で切り取られたHTMLです

<!-- ng-repeat="entry in array track by $index" --> 

<input type="text" class="form-control" 
       datepicker-popup="dd-MMMM-yyyy" 
       is-open="datepickers.isopen[$index]"
       ng-click="valuationDatePickerOpen($event, $index)"
       ng-model="entry.date" />
0
djnose