原文:Ext JS 3.3 Calendar Component
on September 8, 2010 by Brian Moeskau
对一个成熟的日历控件而言,应该可以很轻松地整合之,或本身就可以视其为一个可产品化的项目。不仅如此,通过观察这个日历控件内部原理,你还将看到实现一个Ext组件是多麽的复杂。因此,通过本例子的Sample,你将看到整合过程中,需要一点特殊的技巧性在内。不过另一方面,却也要尽量简单,去掉实际需求中不需要的内容。为此,我们认为在这次的发布中,针对平衡简单与复杂之间的取舍可以获得一个较好的平衡性,以期待您的认同。
认识CalendarPanel
主要的日历演示程序称作CalendarPanel,是一个大头组件,其下面由各个不同的组件所组成。但是你也可以独立使用其中某些的子控件(如各种calendar子视图)。当然CalendarPanel作为大头控件是最高层次的容器并替大部分视图提供所需的配置项参数。所以初初你常会使用到就是这个CalendarPanel。况且她继承自Panel面版类,所以在她身上可以任意套用一种布局风格。
CalendarPanel的渲染实际是通过不同视图组件其模板依次轮流渲染的结果,当然,也可以説CalendarPanel是一个容器。下面,我们来看看CalendarPanel分别有哪些的组件组成:
- MonthView – 通过MonthViewTemplate模板的视图,没有滚动条并总是自适应CalendarPanel大小的。该视图基於box layout的实现。
- DayView – 该试图下细分了两个子视图:DayHeaerView (通过DayHeaderTemplate渲染) 以及 DayBodyView(通过DayBodyTemplate渲染)。头部视图(The header view)位于视图的顶部,是侦听全天事件的所在;而主题视图(The body view)则是非事件区域,可被滚动的区域。这是两种完全不同的视图类型,有着不同的布局方式和事件处理手段等等的区别,所以必须划分开来。
- WeekView –只是DayView的一天的概念扩展到七天,多次渲染而已。这样,也不必要刻意创建多个模板了。
虽然CalendarPanel自带一直默认的编辑形式EventEditorForm,但这仍是远远不够的,你应该根据需求制定新的编辑形式,例如表单验证规则等的属性,预计会有什麽事件,都依据每一个项目的不同而不同。故所以,如果开发你的程序时,通常首先第一步的就是制定日历编辑形式。
CalendarPanel配置项
CalendarPanel类提供许多的配置项参数。通过这些参数,你可以显示或隐藏默认的视图,显示或隐藏默认导航条,显示或隐藏当前的事件以“今天”代替……。子视图也有许多配置项如 enableFx, enableDD, startDay等等。由於使用CalendarPanel 的时候你不能直接访问视图对象,所以要配置子视图的话就必须通过 xxViewConfig的配置项(这个xx可替换为“day,” “week”或“month”)。例如,在例子test-app.js就有针对月视图的配置项内容:monthViewCfg: {
showHeader: true,
showWeekLinks: true,
showWeekNumbers: true
}
控制事件数据
如果熟悉ExtJS组件的数据绑定方式的话,那么为 CalendarPanel加载数据也不是一件难事。只要创建你想要创建的Ext Store类型,用Ext.calendar.EventRecord 去定义记录加载之,再将这个Store绑定到eventStore的这个配置项,那么 CalendarPanel就会完成好数据绑定,自动侦听Store的事件进而更新或渲染UI,整个过程就是与Ext其他的组件相类似。该控件也支持自定义的数据映射(mapping),以便不能直接套用Ext.calendar.EventRecord 的时候。只要指定 Ext.calendar.EventMappings的哪个属性进行覆盖即可。例如:Ext.calendar.EventMappings.Title.mapping = 'my-title'; // 重新定义过id
Ext.calendar.EventMappings.EndDate.name = 'END'; // 重新映射字段
Ext.calendar.EventRecord.reconfigure();
整合在一起吧
如果你看过演示程序的代码,你会发现有两处地方都是登记事件的,一个在CalendarPanel本身一个是在编辑形式EventEditorForm。其目的在于保持组件的低耦合性(loosely-coupled)以便尽量可复用。不同的项目有不同的需求,作为演示程序就是要迎合这种多变的特性,告诉开发者是如何链接这些事件以便完成需求的。不同的日历视图会触发许多特定的事件,如CRUD操作、拖放事件、视图变动。从原理上讲,要更简单地控制事件,CalendarPanel采用了Relay事件的方法——如此便能更集中地控制好这些事件。
依然是老生常谈的话题,UI的交互可能通过事件的设计来产生不同实现,即交互方式决定了事件这么些,好比页面顶部的全局信息告示,单击“快速编辑”显示出来一个窗体等等。
下面将为大家呈现UI代码的大体结构,并特意修葺一下,说明怎么把各种组件组合在一起。可以在示例程序的文件夹下的test-app.js找到完整的代码。
// 设置日历所用的Store数据源
this.calendarStore = new Ext.data.JsonStore({
// 输入配置项
});
this.eventStore = new Ext.data.JsonStore({
// 输入配置项
});
// 设置UI
new Ext.Viewport({
layout: 'border',
items: [{
id: 'app-header',
region: 'north',
// etc. -- static header area
},{
id: 'app-center',
region: 'center',
layout: 'border',
items: [{
id:'app-west',
region: 'west',
// etc. -- sidebar region configs
},{
// 开始定义日历控件
xtype: 'calendarpanel',
region: 'center',
// 日历的数据绑定
eventStore: this.eventStore,
calendarStore: this.calendarStore,
// 自定义视图
monthViewCfg: {
showWeekLinks: true
},
// CalendarPanel-specific configs as
needed
showTime: false
// Set up event listeners -- see the
sample app code for the full list
listeners: {
'eventclick': {
fn: function(vw, rec, el){
// etc.
},
scope: this
},
'eventadd': {
fn: function(cp, rec){
// etc.
},
scope: this
},
// etc. -- there are a lot of these
// These handlers allow the app code
to coordinate between
// components and the overall UI so
that the components
// don't have to know about each other.
}
}]
}]
});
还有……
文章开头已经交待,一个日历控件真正所蕴含的功能要比演示程序中演示的多得多、丰富得多。例如循环事件(指非编程中的“事件”)、并行日历、闹钟和自定义视图等等。就作用而言,该示例程序旨在抛砖引玉所用,从中可以让大家去扩展这个日历控件。但是这里卖一下广告,如果您正想寻找一个一步到位的整合包,那么接下来这个高级版的Ext Calendar Pro
便是不错的选择!