Part 2 - CRUD operation on fullcalender with angularJS



Introduction

In the previous article, I have shown Implement Event/Scheduler calendar using ui-calendar in angularJS, where we have only implemented  a simple scheduling application for showing events using ui-calendar (fullcalender). But without CRUD operation, it can not be a complete solution. So, Today I will show you complete CRUD operation on fullcalender with angularjs for making our application more readable, usable and user-friendly.

Before start, must read Implement Event/Scheduler calendar using ui-calendar in angularJS first.

Read more articles using  AngularJS with ASP.NET.

Just follow the following steps in order to implement "Part 2 - CRUD operation on fullcalender with angularJS".

Here we will start after step 12 of part 1 of this article. 

Step - 13: Update View (HTML) for getting bootstrap modal dialog for CRUD operation.   

Here in this article, we will implement bootstrap modal dialog for CRUD operation.

When user will select calendar time slot by clicking or dragging, the user will get a modal popup for add new events and when will click on any existing events they will get a modal popup for edit/delete that event.

Open your view (here Index.cshtml from Solution Explorer >  Views > Index.cshtml) and update the yellow marked lines.

Complete View (HTML) : 
@{
    ViewBag.Title = "Index";
}
<h2>Event/Scheduler calendar using ui-calendar in AngularJS </h2>
@* HTML *@
<div ng-app="myApp" ng-controller="myNgController">
    
    <script type="text/ng-template" id="modalContent.html">
        <div class="modal-header">
            <h3 class="modal-title">Events</h3>
        </div>
        <div class="modal-body">
            <div class="error">{{Message}}</div>
            <div class="form-group">
                <label>Event Title :</label>
                <input type="text" ng-model="NewEvent.Title" autofocus class="form-control" required />
            </div>
            <div class="form-group">
                <label>Description :</label>
                <textarea ng-model="NewEvent.Description" autofocus class="form-control"></textarea>
            </div>
            <div class="form-group">
                <label>Time Slot :</label>
                <span>
                    {{NewEvent.StartAt}} - {{NewEvent.EndAt}}
                </span>
            </div>
        </div>
        <div class="modal-footer">
            <button class="btn btn-primary" type="button" ng-click="ok()">Save</button>
            <button class="btn btn-danger" type="button" ng-show="NewEvent.EventID > 0" ng-click="delete()">Delete </button>
            <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
        </div>
    </script>
    <div class="row">
        <div class="col-md-12">
            <div id="calendar" ui-calendar="uiConfig.calendar" ng-model="eventSources" calendar="myCalendar"></div>
        </div>
        
        @*<div class="col-md-4">
            <div ng-show="SelectedEvent" class="alert alert-success" style="margin-top:50px">
                <h2 style="margin-top:0px"> Selected Event:</h2>
                <h3 style="color:#A9A50E">{{SelectedEvent.title}}</h3>
                <p>{{SelectedEvent.description}}</p>
            </div>
        </div>*@
    </div>
</div>

@* CSS *@
<link href="~/Content/fullcalendar.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
@* JS *@
<script src="~/Scripts/moment.js"></script>
<script src="~/Scripts/jquery-1.11.3.js"></script>
@*<script src="~/Scripts/angular.js"></script>*@
@* Will use latest angularjs *@
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
<script src="~/Scripts/calendar.js"></script>
<script src="~/Scripts/fullcalendar.js"></script>
<script src="~/Scripts/gcal.js"></script>
@* OUR ANGULAR COMPONENTs *@
<script src="~/Scripts/MyApp.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap-tpls.min.js"></script>
<style>
    .error{
        color:red;
    }
</style>
You can see here
line 8 to line 34, here I have added a ng-template for modal dialog content.
line 58 added a script tag for angular library 1.5.0
line 65 added a script "ui-bootstrap-tpls.min.js" for modal popup
line 66 to line 70 added for add a css class for error message 

Step - 14: Update MyApp.js with followings

Go to Solution Explorer > Scripts > open your angular components file (here in our application "MyApp.js").

Here we will do followings (yellow marked)...
1. Add a function for convert JSON date to DateTime (line 12 - line 20)
2. Add a function for clear events from calendar (line 22 - line 27)
3. Add a function for show events to calendar from database (added existing code for fetch data into this populate function) (line 31 - line 51)
4. Configure ui-calendar for select event by clicking or dragging for add events (line 57 - line 97)
5. Add an angular controller for implement bootstrap modal (line 160 - line 177)
6. Add a function for show modal dialog for CURD operation (line 121 - line 155)


Updated MyApp.js
var app = angular.module('myApp', ['ui.calendar','ui.bootstrap']); // added u.bootstrap for modal dialog
app.controller('myNgController', ['$scope', '$http', 'uiCalendarConfig', '$uibModal', function ($scope, $http, uiCalendarConfig, $uibModal) {
    
    $scope.SelectedEvent = null;
    var isFirstTime = true;

    $scope.events = [];
    $scope.eventSources = [$scope.events];

    $scope.NewEvent = {};
    //this function for get datetime from json date
    function getDate(datetime) {
        if (datetime != null) {
            var mili = datetime.replace(/\/Date\((-?\d+)\)\//, '$1');
            return new Date(parseInt(mili));
        }
        else {
            return "";
        }
    }
    // this function for clear clender enents
    function clearCalendar() {
        if (uiCalendarConfig.calendars.myCalendar != null) {
            uiCalendarConfig.calendars.myCalendar.fullCalendar('removeEvents');
            uiCalendarConfig.calendars.myCalendar.fullCalendar('unselect');
        }
    }
    
    
    // will put this to a method 
    //Load events from server
    $http.get('/home/getevents', {
        cache: true,
        params: {}
    }).then(function (data) {
        $scope.events.slice(0, $scope.events.length);
        angular.forEach(data.data, function (value) {
            $scope.events.push({
                title: value.Title,
                description: value.Description,
                start: new Date(parseInt(value.StartAt.substr(6))),
                end: new Date(parseInt(value.EndAt.substr(6))),
                allDay : value.IsFullDay,
                stick: true
            });
        });
    });
    function populate() {
        clearCalendar();
        $http.get('/home/getevents', {
            cache: false,
            params: {}
        }).then(function (data) {
            $scope.events.slice(0, $scope.events.length);
            angular.forEach(data.data, function (value) {
                $scope.events.push({
                    id : value.EventID,
                    title: value.Title,
                    description: value.Description,
                    start: new Date(parseInt(value.StartAt.substr(6))),
                    end: new Date(parseInt(value.EndAt.substr(6))),
                    allDay: value.IsFullDay,
                    stick: true
                });
            });
        });
    }
    populate();
    //configure calendar
    $scope.uiConfig = {
        calendar: {
            height: 450,
            editable: true,
            displayEventTime: true,
            header: {
                left: 'month,agendaWeek,agendaDay',
                center: 'title',
                right:'today prev,next'
            },
            timeFormat : {
                month : ' ', // for hide on month view
                agenda: 'h:mm t'
            },
            selectable: true,
            selectHelper: true,
            select : function(start, end){
                var fromDate = moment(start).format('YYYY/MM/DD LT');
                var endDate = moment(end).format('YYYY/MM/DD LT');
                $scope.NewEvent = {
                    EventID : 0,
                    StartAt : fromDate,
                    EndAt : endDate,
                    IsFullDay :false,
                    Title : '',
                    Description : ''
                }

                $scope.ShowModal();
            },
            eventClick: function (event) {
                $scope.SelectedEvent = event;
                var fromDate = moment(event.start).format('YYYY/MM/DD LT');
                var endDate = moment(event.end).format('YYYY/MM/DD LT');
                $scope.NewEvent = {
                    EventID : event.id,
                    StartAt : fromDate,
                    EndAt : endDate,
                    IsFullDay :false,
                    Title : event.title,
                    Description : event.description
                }

                $scope.ShowModal();
            },
            eventAfterAllRender: function () {
                if ($scope.events.length > 0 && isFirstTime) {
                    //Focus first event
                    uiCalendarConfig.calendars.myCalendar.fullCalendar('gotoDate', $scope.events[0].start);
                    isFirstTime = false;
                }
            }
        }
    };

    //This function for show modal dialog
    $scope.ShowModal = function () {
        $scope.option = {
            templateUrl: 'modalContent.html',
            controller: 'modalController',
            backdrop: 'static',
            resolve: {
                NewEvent: function () {
                    return $scope.NewEvent;
                }
            }
        };

        var modal = $uibModal.open($scope.option);
        modal.result.then(function (data) {
            $scope.NewEvent = data.event;
            switch (data.operation) {
                case 'Save':
                    //Save here
                    $http({
                        method: 'POST',
                        url: '/home/SaveEvent',
                        data : $scope.NewEvent
                    }).then(function (response) {
                        if (response.data.status) {
                            populate();
                        }
                    })
                    break;
                case 'Delete':
                    //Delete here $http({
                    $http({
                        method: 'POST',
                        url: '/home/DeleteEvent',
                        data: {'eventID' : $scope.NewEvent.EventID }
                    }).then(function (response) {
                        if (response.data.status) {
                            populate();
                        }
                    })
                    break;
                default:
                    break;
            }
        }, function () {
            console.log('Modal dialog closed');
        })
    }

}])

// create a new controller for modal 
app.controller('modalController', ['$scope', '$uibModalInstance', 'NewEvent', function ($scope, $uibModalInstance,NewEvent) {
    $scope.NewEvent = NewEvent;
    $scope.Message = "";
    $scope.ok = function () {
        if ($scope.NewEvent.Title.trim() != "") {
            $uibModalInstance.close({event : $scope.NewEvent, operation: 'Save'});
        }
        else {
            $scope.Message = "Event title required!";
        }
    }
    $scope.delete = function () {
        $uibModalInstance.close({ event: $scope.NewEvent, operation: 'Delete' });
    }
    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    }
}])

Step-15: Add new action into your MVC controller for save Event. 

//Action for Save event
[HttpPost]
public JsonResult SaveEvent(Event evt)
{
    bool status = false;
    using (MyDatabaseEntities dc = new MyDatabaseEntities())
    {
        if (evt.EndAt != null && evt.StartAt.TimeOfDay == new TimeSpan(0,0,0) && 
            evt.EndAt.Value.TimeOfDay == new TimeSpan(0,0,0))
        {
            evt.IsFullDay = true;
        }
        else
        {
            evt.IsFullDay = false;
        }
        if (evt.EventID > 0)
        {
            var v = dc.Events.Where(a => a.EventID.Equals(evt.EventID)).FirstOrDefault();
            if (v != null)
            {
                v.Title = evt.Title;
                v.Description = evt.Description;
                v.StartAt = evt.StartAt;
                v.EndAt = evt.EndAt;
                v.IsFullDay = evt.IsFullDay;
            }
        }
        else
        {
            dc.Events.Add(evt);
        }
        dc.SaveChanges();
        status = true;
    }
    return new JsonResult { Data = new { status = status} };
}

Step-16: Add an another action in our MVC controller for delete Event from the database.

[HttpPost]
public JsonResult DeleteEvent(int eventID)
{
    bool status = false;
    using (MyDatabaseEntities dc = new MyDatabaseEntities())
    {
        var v = dc.Events.Where(a => a.EventID.Equals(eventID)).FirstOrDefault();
        if (v != null)
        {
            dc.Events.Remove(v);
            dc.SaveChanges();
            status = true;
        }
    }
    return new JsonResult { Data = new { status = status } };
}

Step-1: Run Application.


Hello ! My name is Sourav Mondal. I am a software developer working in Microsoft .NET technologies since 2010.

I like to share my working experience, research and knowledge through my site.

I love developing applications in Microsoft Technologies including Asp.Net webforms, mvc, winforms, c#.net, sql server, entity framework, Ajax, Jquery, web api, web service and more.