How to create dynamically datepickers in angularjs

in my angularjs app. I am showing a modal window for editing an event and adding / deleting event dates (I use bootstrap datepicker and timepicker).

the event has certain fixed dates, I have no problem with this because I created them first and I use them on ng-model (datepicker and timepicker).

the problem is when the user clicks the add button to dynamically add new event dates, I don't have a date variable to assign the ng model of the datepicker parameter .

What am I doing to achieve this:

  • inside .controller('ModalEditEventP4ctrl',..I control a modal window (event editing). Here I have an empty object that I use to add new eventdates to the directive addNewDate. $scope.datesObj = {}

  • add a new button eventdate is a directive in which I pass an object of an array of dates from the controller. Inside the directive, I create new date objects and click them on the array to assign it to the html template :

    .directive('addNewDate', function($compile){
      return {
        restrict: 'AE',
        scope: {
            onClick: '&',
            dyndatesObj: '='
        },
        link: function (scope, element, attrs) {
            element.bind('click', function () {                    
            /*1. here i create new date object and push it on the array */
                scope.dyndatesObj.push({dynDateStart:new Date(),dynDateEnd:new Date(),dtStatus:'1'});
    
               /*2. get the last item */
                var items = $(".row.basicDates").length-1;
    
                /*3. compile another directive 'newDateBlock'*/
                /* and pass it into the DOM*/
                /* the directive it is compiled but the datepickers are empty*/
                $('.row.basicDates:eq('+items+')').append($compile("<new-date-block />")(scope));
                scope.$apply();
            });
        }
      }
     })
    
  • a directive newDateBlockin which there are DOM elements that I compile using the ebove directive:

       .directive('newDateBlock', function(){
            return {
                restrict: 'AE',
                scope: {
                    onClick: '&',
                    myDate:'='
                },
                templateUrl: 'assets/modules/part4/templates/addNewDate.tpl.html',
                link: function (scope, element, attrs) {
                    element.bind('click', function () {
                        console.log('inside directive');
                    });
                }
            }
        });
    
  • addNewDate.tpl.html template file (I do not show everything). everything works fine, except from datepickers, which, although I assign them ng-model = dateObj [dateObj.length-1] [dynDateStart] , they are empty.

    <div class="row" >   
    <div class="col-md-6">
       <div class="row">
        <div class="col-md-4" style="padding-left: 0;">
            <label>Start Date</label>
            <label>Start Time</label>
        </div>
        <div class="col-md-8" style="padding-left: 0;">
            <p class="input-group">
                <input type="text" class="form-control" style="width:100px"
                       datepicker-popup="{{format}}"
                     /*ng-model seems not to work*/
                       ng-model="datesObj[datesObj.length-1][dynDateStart]"
                       is-open=""
                       datepicker-options="dateOptions"
                       ng-required="true"
                       close-text="Close"/>
          <span class="input-group-btn" style="float:left">
           <button type="button" class="btn btn-default" ng-click="">
               <i class="glyphicon glyphicon-calendar"></i>
           </button>
          </span>
            </p>
            <timepicker ng-model="" ng-change="changed()" hour-step="1" minute-step="10" show-meridian="false"></timepicker>
        </div>
    </div>
    

enter image description here , ng- , , . .

, ( ), :

TypeError: Cannot read property 'initDate' of undefined
    at link (http://.../bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js:8:23435)
    at http://.../bower_components/angular/angular.min.js:70:141
    at $ (http://.../bower_components/angular/angular.min.js:70:197)
    at B (http://..../bower_components/angular/angular.min.js:59:255)
    at g (http://..../bower_components/angular/angular.min.js:51:335)
    at g (http://..../bower_components/angular/angular.min.js:51:352)
    at g (http:/..../bower_components/angular/angular.min.js:51:352)
    at g (http://.../bower_components/angular/angular.min.js:51:352)
    at g (http://..../bower_components/angular/angular.min.js:51:352)
    at g (http://.../bower_components/angular/angular.min.js:51:352) <input type="text" class="form-control ng-pristine ng-untouched ng-valid ng-isolate-scope" style="width:100px" datepicker-popup="{{format}}" ng-model="datesObj[0].dynDateStart" is-open="" datepicker-options="dateOptions" ng-required="true" close-text="Close">
+4
1

, , $ html , , ng-repeat, , DOM, html, .

:

1. addNewDate():

$scope.addNewDate = function(){
       //i push the new item inside my events.eventDates object and not in another array object as previously
        $scope.eventmodal.eventDates.push({eventStartDate:new Date(),eventEndDate:new Date(),dateStatus:'1'});
            $templateRequest('/assets/modules/part4/templates/addNewDate.tpl.html').then(function(html){

            // Convert the html to an actual DOM node
            var template = angular.element(html);

            // clear completely(not append) the previous block of dates and add the new ones
            $('.basicDatesBlock').html(template);

            // finally $compile the template and show it.
            $compile(template)($scope);
        });
    };

2. my addNewDate.tpl.html ng-repeat, eventDates ( + ) :

<div class="row basicDates" ng-repeat="eventdate in eventmodal.eventDates track by $index" ng-show="eventdate.dateStatus == 1">
<!-- start date -->
<div class="col-md-6">
    <div class="row">
        <div class="col-md-4" style="padding-left: 0;">
            <label>Start Date*</label>
            <label>Start Time</label>
        </div>
        <div class="col-md-8" style="padding-left: 0;">
            <p class="input-group">
                <input type="text" class="form-control" style="width:100px"
                       datepicker-popup="{{format}}"
                       ng-model="eventdate.eventStartDate"
                       is-open="openIndex[$index]"
                       datepicker-options="dateOptions"
                       ng-required="true"
                       close-text="Close"/>
          <span class="input-group-btn" style="float:left">
           <button type="button" class="btn btn-default" ng-click="openme($index)">
               <i class="glyphicon glyphicon-calendar"></i>
           </button>
          </span>
            </p>
            <timepicker ng-model="eventdate.eventStartDate" ng-change="changed()" hour-step="1" minute-step="10" show-meridian="false"></timepicker>
        </div>
    </div>
</div>
<!-- end date -->
<div class="col-md-6">
    <div class="row">
        <div class="col-md-5" style="width:31.6%;padding-right:0;">
            <label>End Date*</label>
            <label>End Time</label>
        </div>
        <div class="col-md-7">
            <p class="input-group">
                <input type="text" class="form-control" style="width:100px"
                       datepicker-popup="{{format}}"
                       ng-model="eventdate.eventEndDate"
                       is-open="openIndex[$index]"
                       datepicker-options="dateOptions"
                       ng-required="true"
                       close-text="Close"/>
                    <span class="input-group-btn" style="float:left">
                       <button type="button" class="btn btn-default" ng-click="openme($index)">
                           <i class="glyphicon glyphicon-calendar"></i>
                       </button>
                    </span>
            </p>
            <!-- i show the '+' button only for the first row-->
            <div style="float:right" ng-show="$index==0">
                <div class="plusCircle" style="margin-top:15px">
                    <!--<div class="plusSymbol" add-new-date  dyndates-obj = datesObj>+</div>-->
                    <div class="plusSymbol" ng-click="addNewBasicDate()">+</div>
                </div>
            </div>
            <!-- i show the 'X' button only for 2nd row and greater-->
            <div style="float:right" ng-show="$index>0">
                <div class="plusCircle" style="margin-top:15px">
                    <div class="plusSymbol">x</div>
                </div>
            </div>

            <timepicker ng-model="eventdate.eventEndDate" ng-change="changed()" hour-step="1" minute-step="10" show-meridian="false"></timepicker>
        </div>
    </div>
</div>

enter image description here . , , .

0

Source: https://habr.com/ru/post/1617008/


All Articles