Como usar o Bootstrap Angular UI Bootstrap em um único formulário?

Eu tenho um formulário onde há a necessidade de eu ter dois ou mais campos de data para coisas diferentes. Eu tentei o Angular UI Bootstrap, que funciona bem quando eu tenho apenas 1 campo de data no formulário. Mas ele pára de funcionar se eu tiver vários campos de data e não sei o método mais fácil de fazer isso funcionar.

Este é o meu exemplo de HTML:

 

Meu 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]; }); 

Eu implementei com base na amostra aqui . O problema que tenho aqui é:

1) Quando um dos campos de data é clicado, o datepicker pop-up é confuso e parece mostrar 2 datepicker em 1.

2) Quando eu removo o atributo is-open="opened" , a janela pop-up parece funcionar bem. Mas sem is-open="opened" , o ng-click="open($event) para o botão não funciona.

3) Como cada um dos campos de data tem ng-models diferentes, não consigo definir datas padrão para nenhum campo de data, exceto o primeiro com ng-model="formData.dt"

O único longo caminho para resolver isso é pensar em separar o controlador para cada campo de data.

Gostaria de saber como os outros implementam vários campos de data em um formulário ao usar o Angular UI Bootstrap.

Eu tenho 30 em um controlador de um formulário não há problema. use o mesmo conceito se você precisar dele em ng-repeat.

   
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]
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 });

Solução mais simples. Requer apenas modding o HTML e pode ser usado em um ng-repeat, se quiser. Basta ser criativo com o que você nomeia de aberto

Cole isso no seu controlador:

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

HTML:

 

A resposta de Wayne é ótima. Gostaria apenas de acrescentar que você pode tornar a function ‘open ()’ melhor:

 $scope.open = function ($event, datePicker) { $event.preventDefault(); $event.stopPropagation(); $scope.closeAll(); datePicker.opened = true; }; 

E então você tem que usá-lo assim:

 ng-click="open($event, dateFrom)" 

Onde dateFrom é o seu ng-model (ou seja, você usa $ scope.dateFrom ).

EDITAR: $scope.closeAll(); é uma function que fecha todos os datePickers. Pode ser escrito assim:

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

Eu prefiro não misturar ng-model com informações de interface do usuário.Para este fim, é necessário definir uma matriz para armazenar os sinalizadores de abertura, bem como verificar se o datePicker está aberto ou não.

Além disso, mudei o comportamento ‘open’ para ‘toggle’, a fim de permitir o fechamento do datePicker com o botão.

Aqui está meu controlador:

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

Então ele pode ser usado como:

     

A ideia do $ scope foi emprestada daqui :

Eu resolvi o meu problema usando este plunker com pequenas alterações.

HTML

 

Popup

e no controlador

 $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; } }; 

minhas mudanças

em vez de números (0 ou 1) eu uso $index em ng-repeat angular.

como isso:

 is-open="openDatePickers[**$index**]" ng-click="open($event, **$index**)" 

Eu usei isso de uma maneira diferente e parece um pouco mais fácil para mim. Eu estava usando uma das abordagens mencionadas, mas eu estava com preguiça de criar toneladas de calendars desde que eu estava executando um loop sem ter qualquer identificador estático. Portanto, esta solução é válida apenas para você, se você quiser criar muitos calendars dentro de uma repetição de ng. Espero que ajude!

Esse é o controlador

  $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; }; 

E este é o HTML cortado dentro do meu loop