-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathExampleDatepicker.fan
151 lines (120 loc) · 5.13 KB
/
ExampleDatepicker.fan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using afIoc
using afBedSheet
using afFormBean
using afDuvet
class ContactUsPage {
@Inject
HttpRequest httpRequest
@Inject { type=ContactDetails# }
FormBean formBean
new make(|This|in) { in(this) }
Text render() {
Text.fromHtml(
"<!DOCTYPE html>
<html>
<head>
<title>FormBean Demo</title>
<link rel='stylesheet' href='/styles.css'>
</head>
<body>
<h2>Contact Us</h2>
<span class='requiredNotification'>* Denotes Required Field</span>
<form class='contactForm' action='/contact' method='POST'>
${ formBean.renderErrors() }
${ formBean.renderBean(null) }
${ formBean.renderSubmit() }
</form>
</body>
</html>")
}
Text onContact() {
// perform server side validation
// if invalid, re-render the page and show the errors
if (!formBean.validateForm(httpRequest.body.form))
return render
// create an instance of our form object
contactDetails := (ContactDetails) formBean.createBean
echo("Contact made!")
echo(" - name: ${contactDetails.name}")
echo(" - email: ${contactDetails.email}")
echo(" - website: ${contactDetails.website}")
echo(" - dob: ${contactDetails.dob}")
echo(" - message: ${contactDetails.message}")
// display a simple message
return Text.fromPlain("Thank you ${contactDetails.name}, we'll be in touch.")
}
}
class ContactDetails {
@HtmlInput { required=true; attributes="placeholder='Fred Bloggs'" }
Str name
@HtmlInput { type="email"; required=true; placeholder="[email protected]"; hint="Proper format '[email protected]'" }
Uri email
@HtmlInput { type="url"; required=true; placeholder="http://www.example.com"; hint="Proper format 'http://someaddress.com'" }
Str website
@HtmlInput { type="date" }
Date dob
@HtmlInput { type="textarea"; required=true; attributes="rows='6'"}
Str message
new make(|This|in) { in(this) }
}
// @SubModule only needed because this example is run as a script
@SubModule { modules=[FormBeanModule#, DuvetModule#] }
const class AppModule {
@Contribute { serviceType=Routes# }
static Void contributeRoutes(Configuration conf) {
conf.add(Route(`/`, ContactUsPage#render))
conf.add(Route(`/contact`, ContactUsPage#onContact, "POST"))
// to save you typing in a stylesheet, we'll just redirect to one I made earlier
// conf.add(Route(`/styles.css`, `styles.css`.toFile))
conf.add(Route(`/styles.css`, Redirect.movedTemporarily(`http://static.alienfactory.co.uk/fantom-docs/afFormBean-quickStart.css`)))
}
@Contribute { serviceType=ScriptModules# }
static Void contributeScriptModules(Configuration config) {
jQuery := ScriptModule("jquery")
.atUrl(`//code.jquery.com/jquery-1.11.1.min.js`)
picker := ScriptModule("datepicker")
.atUrl(`https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.1/js/bootstrap-datepicker.min.js`)
.requires("jquery")
config.add(jQuery)
config.add(picker)
}
@Contribute { serviceType=InputSkins# }
static Void contributeInputSkins(Configuration config) {
config.overrideValue("date", config.build(DateSkin#))
}
@Contribute { serviceType=ValueEncoders# }
static Void contributeValueEncoders(Configuration config) {
config[Date#] = config.build(DateValueEncoder#)
}
}
const class DateSkin : DefaultInputSkin {
@Inject private const HtmlInjector injector
new make(|This| in) { in(this) }
override Str renderElement(SkinCtx skinCtx) {
// Datepicker needs some default Bootstrap styles
injector.injectStylesheet.fromExternalUrl(`https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css`)
// Note you should host the datepicker CSS yourself
injector.injectStylesheet.fromExternalUrl(`https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.1/css/bootstrap-datepicker.min.css`)
injector.injectRequireScript(
["datepicker":"datepicker", "jquery":"\$"],
"\$('#${skinCtx.name}').datepicker({format:'d M yyyy', autoclose: true });"
)
return "<input class='date form-control' type='text' ${skinCtx.renderAttributes} value='${skinCtx.value}'>"
}
}
const class DateValueEncoder : ValueEncoder {
const Str datePattern := "D MMM YYYY"
override Str toClient(Obj? value) {
if (value == null) return Str.defVal
return ((Date) value).toLocale(datePattern)
}
override Obj? toValue(Str clientValue) {
if (clientValue.isEmpty) return null
return Date.fromLocale(clientValue, datePattern)
}
}
class Main {
static Void main() {
BedSheetBuilder(AppModule#).startWisp(8069)
}
}