mattlewis92 / angular-bootstrap-calendar

A port of the bootstrap calendar widget to AngularJS (no jQuery required!)
https://mattlewis92.github.io/angular-bootstrap-calendar/
MIT License
798 stars 369 forks source link

Render events in JSON #134

Closed cvcv01 closed 9 years ago

cvcv01 commented 9 years ago

Hi guys, I'm using the projects demo.js file and trying to load using the events I have on my server.

In demo.js, the default logic goes like this:

vm.calendarView = 'month';
vm.calendarDay = new Date();
vm.events = [
  {
    title: 'An event',
    type: 'warning',
    startsAt: moment().startOf('week').subtract(2, 'days').add(8, 'hours').toDate(),
    endsAt: moment().startOf('week').add(1, 'week').add(9, 'hours').toDate(),
    draggable: true,
    resizable: true
  }, {
    title: '<i class="glyphicon glyphicon-asterisk"></i> <span class="text-primary">Another event</span>, with a <i>html</i> title',
    type: 'info',
    startsAt: moment().subtract(1, 'day').toDate(),
    endsAt: moment().add(5, 'days').toDate(),
    draggable: true,
    resizable: true
  }, {
    title: 'This is a really long event title that occurs on every year',
    type: 'important',
    startsAt: moment().startOf('day').add(7, 'hours').toDate(),
    endsAt: moment().startOf('day').add(19, 'hours').toDate(),
    recursOn: 'year',
    draggable: true,
    resizable: true
  }
];

I'm replacing it with:

vm.calendarView = 'month';
vm.calendarDay = new Date();

$http.get('http://1.1.1.1/project/public/api/events').success(function(events) {    
     vm.events = events;
 });    

my /api/events endpoint looks like this:

{
   "data":[
      {
         "title":"Events",
         "type":"info",
         "startsAt":"2015-07-15 20:49:00",
         "endsAt":"2015-07-15 20:49:00",
         "draggable":"true",
         "resizable":"true"
      },
      {
         "title":"Events",
         "type":"info",
         "startsAt":"2015-07-15 20:53:00",
         "endsAt":"2015-07-15 20:53:00",
         "draggable":"true",
         "resizable":"true"
      },
      {
         "title":"Events",
         "type":"info",
         "startsAt":"2015-07-01 20:59:00",
         "endsAt":"2015-07-01 22:00:00",
         "draggable":"true",
         "resizable":"true"
      },
      {
         "title":"Events",
         "type":"info",
         "startsAt":"2015-07-16 19:42:00",
         "endsAt":"2015-07-16 19:42:00",
         "draggable":"true",
         "resizable":"true"
      },
      {
         "title":"Events",
         "type":"info",
         "startsAt":"2015-07-18 02:12:00",
         "endsAt":"2015-07-18 02:12:00",
         "draggable":"true",
         "resizable":"true"
      }
   ]
}

Unfortunately, I can't get it to work. Is it my json format? Is it my /api/events endpoint not getting picked up? Is it my angular syntax?

Can someone point me in the right direction?

Thanks guys

mattlewis92 commented 9 years ago

If your server is returning the events in the data field then you probably want to do this:

$http.get('http://1.1.1.1/project/public/api/events').success(function(events) {    
     vm.events = events.data;
});  
cvcv01 commented 9 years ago

Thanks, changed my json from data to events instead:

{
   "events":[
      {
         "title":"Events",
         "type":"info",
         "startsAt":"2015-07-15 20:49:00",
         "endsAt":"2015-07-15 20:49:00",
         "draggable":"true",
         "resizable":"true"
      },
      {
         "title":"Events",
         "type":"info",
         "startsAt":"2015-07-15 20:53:00",
         "endsAt":"2015-07-15 20:53:00",
         "draggable":"true",
         "resizable":"true"
      },

Still getting the error: The value passed to current-day attribute of the calendar is not set

mattlewis92 commented 9 years ago

What html are you using? Also are you using controllerAs on your controller?

cvcv01 commented 9 years ago

I'm using the code provided in the demo:

<head> 
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="http://1.1.1.1/project/public/angular-bootstrap-calendar/dist/css/angular-bootstrap-calendar.min.css">
    <link rel="stylesheet" href="http://1.1.1.1/project/public/angular-bootstrap-calendar/docs/styles/main.css">
</head>

<body ng-app="demo" ng-cloak>

<div class="container">
      <div class="row" ng-controller="MainCtrl as vm" id="demo">
        <div class="col-md-12">
          <h2 class="text-center">{{ vm.calendarTitle }}</h2>

          <div class="row">

              <div class="col-md-6 text-center">

                <div class="btn-group">
                <button
                  class="btn btn-primary"
                  mwl-date-modifier
                  date="vm.calendarDay"
                  decrement="vm.calendarView">
                  Previous
                </button>
                <button
                  class="btn btn-default"
                  mwl-date-modifier
                  date="vm.calendarDay"
                  set-to-today>
                  Today
                </button>
                <button
                  class="btn btn-primary"
                  mwl-date-modifier
                  date="vm.calendarDay"
                  increment="vm.calendarView">
                  Next
                </button>
               </div>
            </div>

            <div class="col-md-6 text-center">
              <div class="btn-group">
                <label class="btn btn-primary" ng-model="vm.calendarView" btn-radio="'year'">Year</label>
                <label class="btn btn-primary" ng-model="vm.calendarView" btn-radio="'month'">Month</label>
                <label class="btn btn-primary" ng-model="vm.calendarView" btn-radio="'week'">Week</label>
                <label class="btn btn-primary" ng-model="vm.calendarView" btn-radio="'day'">Day</label>
              </div>
            </div>

        </div>
        <div class="row">
          <mwl-calendar
            events="vm.events"
            view="vm.calendarView"
            view-title="vm.calendarTitle"
            current-day="vm.calendarDay"
            on-event-click="vm.eventClicked(calendarEvent)"
            on-event-times-changed="vm.eventTimesChanged(calendarEvent); calendarEvent.startsAt = calendarNewEventStart; calendarEvent.endsAt = calendarNewEventEnd"
            edit-event-html="'<i class=\'glyphicon glyphicon-pencil\'></i>'"
            delete-event-html="'<i class=\'glyphicon glyphicon-remove\'></i>'"
            on-edit-event-click="vm.eventEdited(calendarEvent)"
            on-delete-event-click="vm.eventDeleted(calendarEvent)"
            auto-open="true"
            day-view-start="06:00"
            day-view-end="22:00"
            day-view-split="30"
            cell-modifier="vm.modifyCell(calendarCell)">
          </mwl-calendar>
        </div>

        <div class="row">
          <script type="text/ng-template" id="modalContent.html">
            <div class="modal-header">
              <h3 class="modal-title">Event action occurred!</h3>
            </div>
            <div class="modal-body">
              <p>Action: <pre>{{ vm.action }}</pre></p>
              <p>Event: <pre>{{ vm.event | json }}</pre></p>
            </div>
            <div class="modal-footer">
              <button class="btn btn-primary" ng-click="$close()">OK</button>
            </div>
          </script>

          <h3 id="event-editor">
            Edit events
            <button class="btn btn-primary pull-right" ng-click="vm.events.push({title: 'New event', type: 'important', draggable: true, resizable: true})">Add new</button>
            <div class="clearfix"></div>
          </h3>

          <table class="table table-bordered">

            <thead>
              <tr>
                <th>Title</th>
                <th>Type</th>
                <th>Starts at</th>
                <th>Ends at</th>
                <th>Remove</th>
              </tr>
            </thead>

            <tbody>
              <tr ng-repeat="event in vm.events track by $index">
                <td><input type="text" class="form-control" ng-model="event.title"></td>
                <td>
                  <select ng-model="event.type" class="form-control">
                    <option value="important">Important</option>
                    <option value="warning">Warning</option>
                    <option value="info">Info</option>
                    <option value="inverse">Inverse</option>
                    <option value="success">Success</option>
                    <option value="special">Special</option>
                  </select>
                </td>
                <td>
                  <p class="input-group" style="max-width: 250px">
                    <input type="text" class="form-control" readonly datepicker-popup="medium" ng-model="event.startsAt" is-open="event.startOpen" close-text="Close" />
                    <span class="input-group-btn">
                      <button type="button" class="btn btn-default" ng-click="vm.toggle($event, 'startOpen', event)"><i class="glyphicon glyphicon-calendar"></i></button>
                    </span>
                  </p>
                  <timepicker ng-model="event.startsAt" hour-step="1" minute-step="15" show-meridian="true"></timepicker>
                </td>
                <td>
                  <p class="input-group" style="max-width: 250px">
                    <input type="text" class="form-control" readonly datepicker-popup="medium" ng-model="event.endsAt" is-open="event.endOpen" close-text="Close" />
                    <span class="input-group-btn">
                      <button type="button" class="btn btn-default" ng-click="vm.toggle($event, 'endOpen', event)"><i class="glyphicon glyphicon-calendar"></i></button>
                    </span>
                  </p>
                  <timepicker ng-model="event.endsAt" hour-step="1" minute-step="15" show-meridian="true"></timepicker>
                </td>
                <td><button class="btn btn-danger" ng-click="vm.events.splice($index, 1)">Delete</button></td>
              </tr>
            </tbody>

          </table>
        </div>

      </div>
      </div>

</div>

    <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.0/moment.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/interact.js/1.2.4/interact.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-touch.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.1/ui-bootstrap-tpls.min.js"></script>
    <script src="http://1.1.1.1/project/public/angular-bootstrap-calendar/dist/js/angular-bootstrap-calendar-tpls.js"></script>
    <script src="http://1.1.1.1/project/public/angular-bootstrap-calendar/docs/scripts/demo.js"></script>
</body>

Does my HTML make sense?

mattlewis92 commented 9 years ago

What happens if you do:

$http.get('http://1.1.1.1/project/public/api/events').success(function(events) {    
     console.log(events);
});  
cvcv01 commented 9 years ago

Ohh, noticed that I get : Error: $http is not defined

mattlewis92 commented 9 years ago

OK add $http to your controller and it should work then.

cvcv01 commented 9 years ago

i'm using the default demo.js file provided, so maybe i'm missing something to use the $http in there?

'use strict';

angular
  .module('demo', ['mwl.calendar', 'ui.bootstrap', 'ngTouch', 'ngAnimate'])
  .controller('MainCtrl', function ($modal, moment) {

var vm = this;
vm.calendarView = 'month';
vm.calendarDay = new Date();
$http.get('http://1.1.1.1/project/public/api/events').success(function(events) {    
    vm.events = events;
}); 
/*
 var currentYear = moment().year();
 var currentMonth = moment().month();

function random(min, max) {
  return Math.floor((Math.random() * max) + min);
}

for (var i = 0; i < 1000; i++) {
  var start = new Date(currentYear,random(0, 11),random(1, 28),random(0, 24),random(0, 59));
 vm.events.push({
    title: 'Event ' + i,
    type: 'warning',
    startsAt: start,
    endsAt: moment(start).add(2, 'hours').toDate()
  })
}*/

function showModal(action, event) {
  $modal.open({
    templateUrl: 'modalContent.html',
    controller: function() {
      var vm = this;
      vm.action = action;
      vm.event = event;
    },
    controllerAs: 'vm'
  });
}   
mattlewis92 commented 9 years ago

You should really read up on how DI works in angular: https://docs.angularjs.org/guide/di

You need to pass it as an argument to the controller.

cvcv01 commented 9 years ago

Thanks Matt, the calendar loaded (without my events though). Changed demo.js like so to fix the "Error: $http is not defined" error:

'use strict';

angular
  .module('demo', ['mwl.calendar', 'ui.bootstrap', 'ngTouch', 'ngAnimate'])
  .controller('MainCtrl', function ($modal, moment, $http) {

var vm = this;
vm.calendarView = 'month';
vm.calendarDay = new Date();
$http.get('http://1.1.1.1/project/public/api/events').success(function(events) {    
    vm.events = events;
}); 
/*
 var currentYear = moment().year();
 var currentMonth = moment().month();

function random(min, max) {
  return Math.floor((Math.random() * max) + min);
}

for (var i = 0; i < 1000; i++) {
  var start = new Date(currentYear,random(0, 11),random(1, 28),random(0, 24),random(0, 59));
 vm.events.push({
    title: 'Event ' + i,
    type: 'warning',
    startsAt: start,
    endsAt: moment(start).add(2, 'hours').toDate()
  })
}*/

function showModal(action, event) {
  $modal.open({
    templateUrl: 'modalContent.html',
    controller: function() {
      var vm = this;
      vm.action = action;
      vm.event = event;
    },
    controllerAs: 'vm'
  });
}   

Now I get : Error: vm.events.filter is not a function in the console. That's another problem

mattlewis92 commented 9 years ago

Initialise vm.events to be an empty array when initialising the controller.

cvcv01 commented 9 years ago

You mean like so? vm.events = [];

'use strict';

angular
  .module('demo', ['mwl.calendar', 'ui.bootstrap', 'ngTouch', 'ngAnimate'])
  .controller('MainCtrl', function ($modal, moment, $http) {

var vm = this;
vm.calendarView = 'month';
vm.calendarDay = new Date();

vm.events = [];

$http.get('http://1.1.1.1/project/public/api/events').success(function(events) {    
    vm.events = events;
}); 

Above outputs same error (Error: vm.events.filter is not a function), maybe not initializing at the right place.

mattlewis92 commented 9 years ago

Yes

cvcv01 commented 9 years ago

That didn't work, still get: Error: vm.events.filter is not a function

mattlewis92 commented 9 years ago

What does output?

$http.get('http://1.1.1.1/project/public/api/events').success(function(events) {    
   console.log(events);
});
cvcv01 commented 9 years ago

It outputs (adds the object events below)

    Object { events: Array[5] }                         demo.js:18:1
    Error: vm.events.filter is not a function               angular

The events array is displayed like so:

events

mattlewis92 commented 9 years ago

There's your problem right there, you're setting the events property to be an object containing the array of events. It needs to directly be the array:

$http.get('http://1.1.1.1/project/public/api/events').success(function(events) {    
   vm.events = events.events;
});
cvcv01 commented 9 years ago

It worked! I can see my events on the calendar now.

The console gives me a warning about the date format I guess:

Bootstrap calendar: Event startsAt should be a javascript date object Object { title: "Events", type: "info", startsAt: "2015-07-15 20:49:00", endsAt: "2015-07-15 20:49:00", draggable: "true", resizable: "true" }

cvcv01 commented 9 years ago

Thanks so much for your help @mattlewis92

Shreeshag commented 8 years ago

Even i am also getting the same warning in console, Can any one please help me to remove warning from console?

Warning will be displayed in console as bellow :

Bootstrap calendar: Event startsAt should be a javascript date object Object {nodeID: "58878", TaskStatus1: "0", SiteStatus: "Under Construction", name: "Task KR 7", spliceID: "alltasks"…}

vicenthy commented 8 years ago

Even i am also getting the same warning in console.

Someone?

Bootstrap calendar: Event endsAt should be a javascript date object. Donew Date(event.endsAt)to fix it. Object {area: Object, color: Object, endOpen: false, endsAt: "2016-09-21 15:00:00", solicitante: Object…} angular.js:13920 Bootstrap calendar: Event startsAt should be a javascript date object. Donew Date(event.startsAt)to fix it. Object {area: Object, color: Object, endOpen: false, endsAt: "2016-09-21 16:00:00", solicitante: Object…}

garrett1276 commented 8 years ago

What are you asking vicenthy? I am not understanding your question. So you have added events to the calendar? The startsAt should be a db.dateTime that is wrapped in a new Date(your db.dateTime)...

vicenthy commented 8 years ago

I use nosql with firebase and my structure is something like

"events":[ { "title":"Events", "type":"info", "startsAt":"2015-07-15 20:49:00", "endsAt":"2015-07-15 20:49:00", "draggable":"true", "resizable":"true" }, { "title":"Events", "type":"info", "startsAt":"2015-07-15 20:53:00", "endsAt":"2015-07-15 20:53:00", "draggable":"true", "resizable":"true" },

and received this Warning in console

Bootstrap calendar: Event startsAt should be a javascript date object. Do new Date(event.startsAt) to fix it. Object {area: Object, color: Object, endOpen: false, endsAt: "2016-09-21 15:00:00", solicitante: Object…}

alejandropichola commented 7 years ago

Angular-bootstrap-calendar I want to consume the dates of an api var calendarController = angular.module('authApp'); calendarController.controller('calendarIndexController', function($filter, moment, alert,proceedingService, authorizationService, calendarConfig, $scope) { var vm = this; vm.calendarView = 'month'; vm.viewDate = new Date();

$scope.date={};
$scope.date.date_st="2017-01-01";
$scope.date.date_end="2017-02-02";
proceedingService.getCalendar($scope.date).success(function(proceedings) {
        $scope.proceedings = proceedings;
});
var actions = [{
  label: '<i class=\'glyphicon glyphicon-pencil\'></i>',
  onClick: function(args) {
    alert.show('Edited', args.calendarEvent);
  }
}, {
  label: '<i class=\'glyphicon glyphicon-remove\'></i>',
  onClick: function(args) {
    alert.show('Deleted', args.calendarEvent);
  }
}];
vm.events = [
  {
    title: 'An event',
    color: calendarConfig.colorTypes.warning,
    startsAt: new Date(('proceeding.proceeding_date')),
    draggable: true,
    resizable: true,
    actions: actions
  }
];
vm.cellIsOpen = true;
vm.addEvent = function() {
  vm.events.push({
    title: 'New event',
    startsAt: moment().startOf('day').toDate(),
    color: calendarConfig.colorTypes.important,
    draggable: true,
    resizable: true
  });
};
vm.eventClicked = function(event) {
  alert.show('Clicked', event);
};
vm.eventEdited = function(event) {
  alert.show('Edited', event);
};
vm.eventDeleted = function(event) {
  alert.show('Deleted', event);
};
vm.eventTimesChanged = function(event) {
  alert.show('Dropped or resized', event);
};
vm.toggle = function($event, field, event) {
  $event.preventDefault();
  $event.stopPropagation();
  event[field] = !event[field];
};
vm.timespanClicked = function(date, cell) {
  if (vm.calendarView === 'month') {
    if ((vm.cellIsOpen && moment(date).startOf('day').isSame(moment(vm.viewDate).startOf('day'))) || cell.events.length === 0 || !cell.inMonth) {
      vm.cellIsOpen = false;
    } else {
      vm.cellIsOpen = true;
      vm.viewDate = date;
    }
  } else if (vm.calendarView === 'year') {
    if ((vm.cellIsOpen && moment(date).startOf('month').isSame(moment(vm.viewDate).startOf('month'))) || cell.events.length === 0) {
      vm.cellIsOpen = false;
    } else {
      vm.cellIsOpen = true;
      vm.viewDate = date;
    }
  }
};

}); authApp.factory('alert', function($uibModal) { function show(action, event) { return $uibModal.open({ templateUrl: '../../views/calendar/modalContent.html', controller: function() { var vm = this; vm.action = action; vm.event = event; }, controllerAs: 'vm' }); } return { show: show }; });

moment.locale('es', { week : { dow : 7 } });

authApp.config(['calendarConfig', function(calendarConfig) { console.log(calendarConfig); calendarConfig.templates.calendarDayView = '../../views/calendar/templates/calendarDayView.html'; calendarConfig.templates.calendarHourList = '../../views/calendar/templates/calendarHourList.html'; calendarConfig.templates.calendarMonthCell = '../../views/calendar/templates/calendarMonthCell.html'; calendarConfig.templates.calendarMonthCellEvents = '../../views/calendar/templates/calendarMonthCellEvents.html'; calendarConfig.templates.calendarMonthView = '../../views/calendar/templates/calendarMonthView.html'; calendarConfig.templates.calendarSlideBox = '../../views/calendar/templates/calendarSlideBox.html'; calendarConfig.templates.calendarWeekView = '../../views/calendar/templates/calendarWeekView.html'; calendarConfig.dateFormatter = 'moment'; }]);

/*$scope.CreateCalendar= function(){

} */