PDA

View Full Version : [CLOSED] Customizing Edit Event Details Window of Calendar.



Suntico
Jul 05, 2012, 10:45 AM
Hi,

We are using the Ext.Net 2.x in our MVC3 Application. We have successfully added and handled some custom fields in "Edit Event" window (Popup). But after researching from various threads we were unable to figure out that how can we add these custom fields to the "Edit Details" window (opened on second click).

Further more there is a issue in "Edit Details" window (opened on Second click) in EXT.Net examples as well(http://examples2.ext.net/#/Calendar/Overview/Remote_Data/). You can replicate this issue by opening the "Edit Detail" window (opened on second click) and try to delete an event. (Attached is the screen shot)

4443

Following is our code please suggest us how can we achieve our requirement of adding the custom fields to the Edit Details window.

--------------------------------------------------------------- Our View.cshtml (Start) --------------------------------------------------------------------------------


@{
//Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";
Layout = null;
}
<link rel="stylesheet" type="text/css" href="../../Content/CalendarThemes/resources/css/main.css" />
<script src="../../Scripts/CalendarScripts/Ext.Net.Calendar/common.js" type="text/javascript"></script>

@using Ext.Net.MVC;
@model System.Data.DataSet

@(Html.X().ResourceManager()
.ScriptMode(Ext.Net.ScriptMode.Debug)
.IDMode(IDMode.Parent)
.Namespace("Event")
)

@(Html.X().Viewport()
.Layout(LayoutType.Border)
.Items(vItems => vItems
.Add(
Html.X().Panel()
.Border(false)
.Region(Region.North))
.Add(
Html.X().Panel()
.ID("Panel1")
.ItemID("Panel1")
.Title("...")
.Layout(LayoutType.Border)
.Region(Region.Center)
.Items(pItems => pItems
.Add(Html.X().Panel()
.Region(Region.West)
.Border(false)
.Add(
Html.X().DatePicker()
.ID("DatePicker1")
.ItemID("DatePicker1")
.Listeners(dpListner =>
{
dpListner.Select.Fn = "Event.setStartDate";
dpListner.Select.Scope = "Event";
})
)
)
)
.Add(
Html.X().CalendarPanel()
.ID("CalendarPanel1")
.ItemID("CalendarPanel1")
.Region(Region.Center)
.ActiveIndex(1)
.MonthView(
Html.X().MonthView()
.ShowHeader(true)
.ShowWeekLinks(true)
.ShowWeekNumbers(true))
.CalendarStore(
Html.X().CalendarStore()
.ID("CalendarStore1")
.ItemID("CalendarStore1")
.Calendars(delegate(CalendarModelCollection i)
{
i.Add(new CalendarModel { CalendarId = 1, Title = "Meeting" });
i.Add(new CalendarModel { CalendarId = 2, Title = "Appointment" });
i.Add(new CalendarModel { CalendarId = 3, Title = "Task" });
i.Add(new CalendarModel { CalendarId = 4, Title = "Event" });
i.Add(new CalendarModel { CalendarId = 5, Title = "Other" });
})
)
.EventStore(
Html.X().EventStore()
.ID("EventStore1")
.ItemID("EventStore1")
.NoMappings(true)
.DataSource(this.Model.Tables[0])
.Mappings(mapFields =>
{
mapFields.Add(Html.X().ModelField().Name("StartDate").Type(ModelFieldType.Date).Mapping("StartDate"));
mapFields.Add(Html.X().ModelField().Name("EndDate").Type(ModelFieldType.Date).Mapping("EndDate"));
mapFields.Add(Html.X().ModelField().Name("EventId").Type(ModelFieldType.Auto).Mapping("HOCode"));
mapFields.Add(Html.X().ModelField().Name("CalendarId").Type(ModelFieldType.Auto).Mapping("ActivityType"));
mapFields.Add(Html.X().ModelField().Name("Title").Type(ModelFieldType.Auto).Mapping("title"));
mapFields.Add(Html.X().ModelField().Name("Notes").Type(ModelFieldType.Auto).Mapping("body"));
mapFields.Add(Html.X().ModelField().Name("Attendees").Type(ModelFieldType.Auto));
}))
.Listeners( // Listeners
listners =>
{
listners.DayClick.Fn = "Event.dayClick"; listners.DayClick.Scope = "Event";
listners.RangeSelect.Fn = "Event.rangeSelect"; listners.RangeSelect.Scope = "Event";
listners.ViewChange.Fn = "Event.viewChange"; listners.ViewChange.Scope = "Event";
listners.EventMove.Fn = "Event.record.move"; listners.EventMove.Scope = "Event";
listners.EventClick.Fn = "Event.record.show"; listners.EventClick.Scope = "Event";
listners.EventResize.Fn = "Event.record.resize"; listners.EventResize.Scope = "Event";
listners.EventDelete.Fn = "Event.record.remove";
})
)
))
)
@(Html.X().EventWindow()
.ID("EventEditWindow1")
.ItemID("EventEditWindow1")
.CalendarStoreID("CalendarStore1")
.Hidden(true)
.Listeners(
listener =>
{
listener.EventAdd.Fn = "Event.record.add"; listener.EventAdd.Scope = "Event";
listener.EditDetails.Fn = "Event.record.edit"; listener.EditDetails.Scope = "Event";
listener.EventUpdate.Fn = "Event.record.update"; listener.EventUpdate.Scope = "Event";
listener.EventDelete.Fn = "Event.record.remove"; listener.EventDelete.Scope = "Event";
})
)



<style type="text/css">
.ext-color-4,
.ext-ie .ext-color-4-ad,
.ext-opera .ext-color-4-ad {
color: #717D7D;
}
.ext-cal-day-col .ext-color-4,
.ext-dd-drag-proxy .ext-color-4,
.ext-color-4-ad,
.ext-color-4-ad .ext-cal-evm,
.ext-color-4 .ext-cal-picker-icon,
.ext-color-4-x dl,
.ext-color-4-x .ext-cal-evb {
background: #717D7D;
}
.ext-color-4-x .ext-cal-evb,
.ext-color-4-x dl {
border-color: #7C3939;
}
.ext-color-5,
.ext-ie .ext-color-5-ad,
.ext-opera .ext-color-5-ad {
color: #B43104;
}
.ext-cal-day-col .ext-color-5,
.ext-dd-drag-proxy .ext-color-5,
.ext-color-5-ad,
.ext-color-5-ad .ext-cal-evm,
.ext-color-5 .ext-cal-picker-icon,
.ext-color-5-x dl,
.ext-color-5-x .ext-cal-evb {
background: #B43104;
}
.ext-color-5-x .ext-cal-evb,
.ext-color-5-x dl {
border-color: #7C3939;
}
</style>

------------------------------------------------------------------- View.cshtml (End) -----------------------------------------------------------------------

------------------------------------------------------------------- common.js (Start) -----------------------------------------------------------------------

var sDate, eDate, aDate, record, confirmWindow;
var Event = {
getCalendar: function () {
return Event.CalendarPanel1;
},

getStore: function () {
return Event.EventStore1;
},

getWindow: function () {
return Event.EventEditWindow1;
},
viewChange: function (p, vw, dateInfo) {
var win = this.getWindow();
if (win) {
win.hide();
}

if (dateInfo !== "undefined" | dateInfo !== null) {

// Modifications
if (sDate == null | eDate == null) {
sDate = dateInfo.viewStart;
eDate = dateInfo.viewEnd;
aDate = dateInfo.activeDate;

this.DatePicker1.setValue(dateInfo.activeDate);
this.updateTitle(dateInfo.viewStart, dateInfo.viewEnd);
}
else if (dateInfo == null | dateInfo == "undefined") { //
this.DatePicker1.setValue(aDate); // if dateInfo is undefined/null
this.updateTitle(sDate, eDate); //
}
else if (sDate != dateInfo.viewStart | eDate != dateInfo.viewEnd) { //
this.DatePicker1.setValue(dateInfo.activeDate); // if View change
this.updateTitle(dateInfo.viewStart, dateInfo.viewEnd); //
}
// Modification End
}
},

updateTitle: function (startDt, endDt) {
var title = startDt.toDateString().substring(4, 10) + " - " + endDt.toDateString().substring(4, 10) + ", " + startDt.getFullYear();
this.Panel1.setTitle(title);
},

setStartDate: function (picker, date) {
this.getCalendar().setStartDate(date);
},

rangeSelect: function (cal, dates, callback) {
this.record.show(cal, dates);
this.getWindow().on('hide', callback, cal, { single: true });
},

dayClick: function (cal, dt, allDay, el) {
this.record.show.call(this, cal, {
StartDate: dt,
IsAllDay: allDay
}, el);
},
showResultText: function (btn) {
if (btn == "yes") {
var operationObj = {
TYPE: 'DELETE',
objdat: [
record.data.EventId
]
}
Ext.Ajax.request({
url: "../Calendar/CRUD",
cleanRequest: true,
params: operationObj,
success: function (result) {
Event.getStore().remove(record);
confirmWindow.hide();
Ext.Msg.notify("Event", '<b style="text-transform: uppercase">' + record.data.Title + '</b>' + " deleted");
},
error: function (result) {
Ext.Msg.alert("Error", "An error occurd while deleting data");
}
});
}
},
record: {
add: function (win, rec) {
var operationObj = {
TYPE: 'SAVE',
objdat: [
0,
rec.data.CalendarId,
rec.data.Title,
rec.data.StartDate,
rec.data.EndDate,
rec.data.IsAllDay,
rec.data.Notes,
rec.data.Url,
rec.data.Reminder,
rec.data.Location,
rec.data.IsNew,
rec.data.Attendees
]
}

win.hide();
rec.data.IsNew = true;
Ext.Ajax.request({
url: "../Calendar/CRUD",
cleanRequest: true,
params: operationObj,
success: function (result) {
rec.data.EventId = result.responseText;
Event.getStore().add(rec);
Event.ShowMsg('Event', '<b style="text-transform: uppercase">' + rec.data.Title + '</b>' + ' added');
},
error: function (result) {
Ext.Msg.alert("Error", "An error occurd while saving data");
}
});
},
update: function (win, rec) {
var operationObj = {
TYPE: 'UPDATE',
objdat: [
rec.data.EventId,
rec.data.CalendarId,
rec.data.Title,
rec.data.StartDate,
rec.data.EndDate,
rec.data.IsAllDay,
rec.data.Notes,
rec.data.Url,
rec.data.Reminder,
rec.data.Location,
rec.data.IsNew,
rec.data.Attendees
]
}
win.hide();
rec.commit();
Ext.Ajax.request({
url: "../Calendar/CRUD",
cleanRequest: true,
params: operationObj,
success: function (result) {
Event.ShowMsg('Event', '<b style="text-transform: uppercase">' + rec.data.Title + '</b>' + ' updated');
},
error: function (result) {
Ext.Msg.alert("Error", "An error occurd while updating data");
}
});
},

remove: function (win, rec) {
confirmWindow = win;
Ext.Msg.confirm("Delete Confirmation", "Are you sure you want to do delete " + rec.data.Title + "?", Event.showResultText);
record = rec;
},

edit: function (win, rec) {
win.hide();
Event.getCalendar().showEditForm(rec);
},

resize: function (cal, rec) {
var operationObj = {
TYPE: 'UPDATE',
objdat: [
rec.data.EventId,
rec.data.CalendarId,
rec.data.Title,
rec.data.StartDate,
rec.data.EndDate,
rec.data.IsAllDay,
rec.data.Notes,
rec.data.Url,
rec.data.Reminder,
rec.data.Location,
rec.data.IsNew,
rec.data.Attendees
]
}
Ext.Ajax.request({
url: "../Calendar/CRUD",
cleanRequest: true,
params: operationObj,
success: function (result) {
rec.commit();
Event.ShowMsg('Event', '<b style="text-transform: uppercase">' + rec.data.Title + '</b>' + ' time updated' + " from: " + '<b style="text-transform: uppercase">' + rec.data.StartDate.toLocaleTimeString() + '</b>' + " to: " + '<b style="text-transform: uppercase">' + rec.data.EndDate.toLocaleTimeString() + '</b>');
},
error: function (result) {
Ext.Msg.alert("Error", "An error occurd while updating data");
}
});
},

move: function (cal, rec) {
var operationObj = {
TYPE: 'UPDATE',
objdat: [
rec.data.EventId,
rec.data.CalendarId,
rec.data.Title,
rec.data.StartDate,
rec.data.EndDate,
rec.data.IsAllDay,
rec.data.Notes,
rec.data.Url,
rec.data.Reminder,
rec.data.Location,
rec.data.IsNew,
rec.data.Attendees
]
}
Ext.Ajax.request({
url: "../Calendar/CRUD",
cleanRequest: true,
params: operationObj,
success: function (result) {
rec.commit();
Event.ShowMsg('Event', '<b style="text-transform: uppercase">' + rec.data.Title + '</b>' + ' moved to ' + '<b style="text-transform: uppercase">' + rec.data.StartDate.toLocaleTimeString() + '</b>' + " at, " + '<b style="text-transform: uppercase">' + rec.data.StartDate.toDateString() + '</b>');
},
error: function (result) {
Ext.Msg.alert("Error", "An error occurd while updating data");
}
});
},

show: function (cal, rec, el) {
if (rec.data == "" | rec.data == null) {
Event.getWindow().show(rec, el);
}
else {
var operationObj = {
TYPE: 'READ',
objdat: [rec.data.EventId]
}
Ext.Ajax.request({
url: "../Calendar/CRUD",
cleanRequest: true,
params: operationObj,
success: function (result) {
rec.data.Attendees = result.responseText;
Event.getWindow().show(rec, el);
},
error: function (result) {
Ext.Msg.alert("Error", "An error occurd while getting event attendees");
}
});
}
},

saveAll: function () {
Event.getStore().submitData();
}
},

ShowMsg: function (EventTitle, record) {
Ext.Msg.notify(EventTitle, record.toString());
}
};
Ext.calendar.form.EventWindow.override({
constructor: function (config) {
var formPanelCfg = {
xtype: 'form',
fieldDefaults: {
msgTarget: 'side',
labelWidth: 65
},
frame: false,
bodyStyle: 'background:transparent;padding:5px 10px 10px;',
bodyBorder: false,
border: false,
items: [
{
itemId: 'title',
name: Ext.calendar.data.EventMappings.Title.name,
fieldLabel: 'Title',
xtype: 'textfield',
anchor: '100%',
allowBlank: false
},
{
itemId: 'Description',
name: Ext.calendar.data.EventMappings.Notes.name,
fieldLabel: 'Description',
xtype: 'textarea',
anchor: '100%',
allowBlank: false
},
{
xtype: 'daterangefield',
itemId: 'date-range',
name: 'dates',
anchor: '100%',
fieldLabel: 'When'
}]
};

if (config.calendarStore) {
this.calendarStore = config.calendarStore;
delete config.calendarStore;

formPanelCfg.items.push
(
{
xtype: 'calendarpicker',
itemId: 'calendar',
name: Ext.calendar.data.EventMappings.CalendarId.name,
anchor: '100%',
store: this.calendarStore
},
{
itemId: 'Attendees',
id: 'Attendees',
name: Ext.calendar.data.EventMappings.Attendees.name,
fieldLabel: 'Attendees',
xtype: 'textfield',
anchor: '100%',
store: this.calendarStore
}
);
}

this.callParent([Ext.apply({
titleTextAdd: 'Add Event',
titleTextEdit: 'Edit Event',
width: 600,
autocreate: true,
border: true,
closeAction: 'hide',
modal: true,
resizable: false,
buttonAlign: 'left',
savingMessage: 'Saving changes...',
deletingMessage: 'Deleting event...',
layout: 'fit',

fbar: [{
xtype: 'tbtext',
text: '<a href="#" id="tblink" style="text-decoration:underline">Edit Details...</a>'
},
'->', {
text: 'Save',
disabled: false,
handler: this.onSave,
scope: this
},
{
itemId: 'delete-btn',
text: 'Delete',
disabled: false,
handler: this.onDelete,
scope: this,
hideMode: 'offsets'
},
{
text: 'Cancel',
disabled: false,
handler: this.onCancel,
scope: this
}],
items: formPanelCfg
},
config)]);
}
});
Ext.calendar.form.field.DateRange.override({
dateFormat: "Y-m-d"
});

------------------------------------------------------------------- common.js (End) -----------------------------------------------------------------------

---------------------------------------------------------------- Controller-Actions (start) ------------------------------------------------------------------


public ActionResult Index()
{
try
{ return View(FetchData()); }
catch (Exception)
{ return View(new DataSet { }); }
}

public string CRUD(List<object> objdat, string TYPE)
{
try
{
switch(TYPE)
{
// Update Operation //
// Delete Operation //
// Read Operation //
};

if (emailAddresses != null)
{
return emailAddresses;
}
else
{
return Convert.ToString(newID);
}
}
catch (Exception)
{ return "false"; }
}

---------------------------------------------------------------- Controller-Actions (End) ------------------------------------------------------------------

Daniil
Jul 05, 2012, 1:03 PM
Hi,

We have reproduced the issue and investigating a possible fix.

Thanks for the report.

Suntico
Jul 05, 2012, 1:08 PM
Hi,

We have reproduced the issue and investigating a possible fix.

Thanks for the report.

Please do also tell me how can we add our custom fields to "Edit Details" Window. We have already added our custom fields in the "Edit Event" Window but are facing problems in adding them in "Edit Details" Window.

Daniil
Jul 05, 2012, 5:43 PM
1. Please replace:

this.getStore().remove(rec);
with

CompanyX.getStore().remove(rec);
with the CompanyX.record.remove function.

2. Regarding the server Exception.

When the Delete button is pressed with the details form, the current event is removed and the store initiates a sync request to save that change immediately to server. So, the "sync" link should be defined in the AjaxProxy.

Example

<ext:AjaxProxy Url="../Shared/Code/RemoteService.asmx/GetEvents" Json="true">
<API Sync="some sync url" />
</ext:AjaxProxy>

I think we will show a respective message in our example. Please thanks for the report.

3. Regarding custom fields within the details form.

Unfortunately, we have no such example for Ext.NET v2.

Here is the example for Ext.NET v1.
http://forums.ext.net/showthread.php?14093&p=59318&viewfull=1#post59318

It will look similar in Ext.NET v2, the principle will be the same.

You might need to look at the Calendar JavaScript sources. There are the helpful comments.
<Ext.Net v2 sources root>\Ext.Net\Build\Ext.Net\ux\calendar\src\CalendarPan el.js

Daniil
Jul 06, 2012, 1:20 PM
The issues have been fixed in SVN.

The online examples will be updated with the upcoming release.

Thanks again for the report.

Daniil
Apr 19, 2013, 6:34 AM
3. Regarding custom fields within the details form.

Unfortunately, we have no such example for Ext.NET v2.

Here is the example for Ext.NET v1.
http://forums.ext.net/showthread.php?14093&p=59318&viewfull=1#post59318

It will look similar in Ext.NET v2, the principle will be the same.

You might need to look at the Calendar JavaScript sources. There are the helpful comments.
<Ext.Net v2 sources root>\Ext.Net\Build\Ext.Net\ux\calendar\src\CalendarPan el.js

Here is an example of adding custom fields to EventStore and EventWindow.

Example Page

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
class MyEventModel : EventModel
{
public string Test1 { get; set; }
public string Test2 { get; set; }
}

protected void Page_Load(object sender, EventArgs e)
{
Model model = this.CalendarPanel1.EventStore.ModelInstance;
model.Fields.Add(new ModelField("Test1"));
model.Fields.Add(new ModelField("Test2"));

this.CalendarPanel1.EventStore.Model.Add(model);

if (!X.IsAjaxRequest)
{
EventStore store = this.CalendarPanel1.EventStore;
store.Events.AddRange(new List<MyEventModel>
{
new MyEventModel()
{
Title = "My event",
CalendarId = 1,
StartDate = DateTime.Now,
EndDate = DateTime.Now.AddDays(1),
EventId = 1,
Test1 = "I'm the first",
Test2 = "I'm the second"
}
});
}
}

protected void EventStore_SubmitData(object sender, StoreSubmitDataEventArgs e)
{
MyEventModel[] events = JSON.Deserialize<MyEventModel[]>(e.Json);
X.Msg.Alert("Submitted", JSON.Serialize(events)).Show();
}
</script>

<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.NET v2 Example</title>

<script type="text/javascript" src="/resources/js/EventMappings.js"></script>
<script type="text/javascript" src="/resources/js/EventWindow.js"></script>
<script type="text/javascript" src="/resources/js/common.js"></script>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" Namespace="CompanyX" />

<ext:Viewport runat="server" Layout="FitLayout">
<Items>
<ext:CalendarPanel ID="CalendarPanel1" runat="server">
<EventStore ID="EventStore1" runat="server" OnSubmitData="EventStore_SubmitData">
<Listeners>
<BeforeSync Handler="return false;" />
</Listeners>
</EventStore>
<CalendarStore ID="CalendarStore1" runat="server">
<Calendars>
<ext:CalendarModel CalendarId="1" Title="Home" />
<ext:CalendarModel CalendarId="2" Title="Work" />
<ext:CalendarModel CalendarId="3" Title="School" />
</Calendars>
</CalendarStore>
<Listeners>
<EventClick Fn="CompanyX.record.show" Scope="CompanyX" />
<DayClick Fn="CompanyX.dayClick" Scope="CompanyX" />
</Listeners>
<Buttons>
<ext:Button runat="server" Text="Submit" Handler="CompanyX.record.saveAll()" />
</Buttons>
</ext:CalendarPanel>
</Items>
</ext:Viewport>

<ext:EventWindow
ID="EventWindow1"
runat="server"
Hidden="true"
CalendarStoreID="CalendarStore1">
<Listeners>
<EventAdd Fn="CompanyX.record.add" Scope="CompanyX" />
<EventUpdate Fn="CompanyX.record.update" Scope="CompanyX" />
<EditDetails Fn="CompanyX.record.edit" Scope="CompanyX" />
<EventDelete Fn="CompanyX.record.remove" Scope="CompanyX" />
</Listeners>
</ext:EventWindow>
</form>
</body>
</html>

EventMappings.js

Ext.apply(Ext.calendar.data.EventMappings, {
Test1: {
name: 'Test1',
mapping: 'test1',
type: 'string'
},
Test2: {
name: 'Test2',
mapping: 'test2',
type: 'string'
}
});

//needs to reconfigure EventModel
Ext.calendar.data.EventModel.reconfigure();


EventWindow.js

Ext.calendar.form.EventWindow.override({
constructor: function(config) {
this.callParent(arguments);

var form = this.child("form");

form.add([{
itemId: 'test1',
name: Ext.calendar.data.EventMappings.Test1.name,
fieldLabel: 'Test1',
xtype: 'textfield',
anchor: '100%'
}, {
itemId: 'test2',
name: Ext.calendar.data.EventMappings.Test2.name,
fieldLabel: 'Test2',
xtype: 'textfield',
anchor: '100%'
}]);
}
});

common.js

var CompanyX = {
getStore: function () {
return CompanyX.EventStore1;
},

getWindow: function () {
return CompanyX.EventWindow1;
},

dayClick: function (cal, dt, allDay, el) {
this.record.show.call(this, cal, {
StartDate: dt,
IsAllDay: allDay
}, el);
},

record: {
add: function (win, rec) {
win.hide();
CompanyX.getStore().add(rec);
CompanyX.getStore().sync();
},

update: function (win, rec) {
win.hide();
rec.commit();
CompanyX.getStore().sync();
},

remove: function (win, rec) {
CompanyX.getStore().remove(rec);
CompanyX.getStore().sync();
win.hide();
},

edit: function (win, rec) {
win.hide();
rec.commit();
CompanyX.getCalendar().showEditForm(rec);
},

show: function (cal, rec, el) {
CompanyX.getWindow().show(rec, el);
},

saveAll: function () {
CompanyX.getStore().submitData({
mappings: false
});
}
}
};