Vaadin:在日期字段的字段焦点上打开日历
Vaadin: open calendar on field focus for datefield
Vaadin 小部件既简单又很棒!但它们的可配置性也很差。
我需要我的 DateField 小部件才能在焦点事件上打开日历。我没有在官方 Vaadin documentation. I found some 3rd party widget here 中找到该功能,但它是为 Vaadin 7.7 编译的,我使用最新的 Vaadin (8.0.6)。它还具有 Joda-time 2.1 依赖性,这在我的项目中是非常不受欢迎的。那么,是否有任何简单的方法来调整股票 vaadin DateField 小部件以在字段焦点上打开它的日历,或者我是否需要为此编写自己的组件?任何帮助表示赞赏。
正如我在评论中所说,据我所知,目前该框架不提供以编程方式打开日历弹出窗口的隐式方式。同样的事情也适用于其他一些组件,例如网格编辑器或组合项列表。
我能想到的一个快速解决方法是添加一个 javascript extension 来为所有日期字段注册焦点侦听器,并在日期字段获得焦点时单击按钮。请在下面找到一个示例。
P.S。如果您只需要将此应用于某些日期字段,您可以添加 ID 并将它们传递给 JS,您将在 JS 中执行类似 document.getElementById('myDateFieldId')
而不是 document.getElementsByClassName("v-datefield")
.
的操作
1) 组件布局
public class MyDateFieldComponent extends HorizontalLayout {
public MyDateFieldComponent() {
// basic setup
DateField fromDateField = new DateField("From", LocalDate.of(2011, Month.FEBRUARY, 6));
DateField toDateField = new DateField("To", LocalDate.of(2018, Month.FEBRUARY, 6));
setSpacing(true);
addComponents(fromDateField, toDateField);
// add the extension
addExtension(new CalendarFocusPopupOpenerExtension());
}
}
2) 分机 - java/server 边
import com.vaadin.annotations.JavaScript;
import com.vaadin.server.AbstractJavaScriptExtension;
@JavaScript("calendar-focus-popup-opener-extension.js")
public class CalendarFocusPopupOpenerExtension extends AbstractJavaScriptExtension {
public CalendarFocusPopupOpenerExtension() {
// call the bind function defined in the associated JS
callFunction("bind");
}
}
3) 分机 - js/client 边
window.com_example_calendar_CalendarFocusPopupOpenerExtension = function () {
this.bind = function () {
if (document.readyState === "complete") {
// if executed when document already loaded, just bind
console.log("Doc already loaded, binding");
bindToAllDateFields();
} else {
// otherwise, bind when finished loading
console.log("Doc nod loaded, binding later");
window.onload = function () {
console.log("Doc finally loaded, binding");
bindToAllDateFields();
}
}
};
function bindToAllDateFields() {
// get all the date fields to assign focus handlers to
var dateFields = document.getElementsByClassName("v-datefield");
for (var i = 0; i < dateFields.length; i++) {
addFocusListeners(dateFields[i]);
}
}
function addFocusListeners(dateField) {
// when focusing the date field, click the button
dateField.onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
// or when focusing the date field input, click the button
dateField.getElementsByTagName("input")[0].onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
}
};
4) 结果
稍后更新
第二种方法可能是为您的字段分配一些 ID,然后定期检查以查看所有字段何时可见,一旦可见,就绑定焦点侦听器。
1) 组件布局
public class MyDateFieldComponent extends HorizontalLayout {
public MyDateFieldComponent() {
// basic setup
DateField fromDateField = new DateField("From", LocalDate.of(2011, Month.FEBRUARY, 6));
fromDateField.setId("fromDateField"); // use id to bind
fromDateField.setVisible(false); // initially hide it
DateField toDateField = new DateField("To", LocalDate.of(2018, Month.FEBRUARY, 6));
toDateField.setId("toDateField"); // use id to bind
toDateField.setVisible(false); // initially hide it
// simulate a delay until the fields are available
Button showFieldsButton = new Button("Show fields", e -> {
fromDateField.setVisible(true);
toDateField.setVisible(true);
});
setSpacing(true);
addComponents(showFieldsButton, fromDateField, toDateField);
// add the extension
addExtension(new CalendarFocusPopupOpenerExtension(fromDateField.getId(), toDateField.getId()));
}
}
2) 分机 - java/server 边
@JavaScript("calendar-focus-popup-opener-extension.js")
public class CalendarFocusPopupOpenerExtension extends AbstractJavaScriptExtension {
public CalendarFocusPopupOpenerExtension(String... idsToBindTo) {
// send the arguments as an array of strings
JsonArray arguments = Json.createArray();
for (int i = 0; i < idsToBindTo.length; i++) {
arguments.set(i, idsToBindTo[i]);
}
// call the bind defined in the associated JS
callFunction("bind", arguments);
}
}
3) 分机 - js/client 边
window.com_example_calendar_CalendarFocusPopupOpenerExtension = function () {
var timer;
this.bind = function (idsToBindTo) {
// check every second to see if the fields are available. interval can be tweaked as required
timer = setInterval(function () {
bindWhenFieldsAreAvailable(idsToBindTo);
}, 1000);
};
function bindWhenFieldsAreAvailable(idsToBindTo) {
console.log("Looking for the following date field ids: [" + idsToBindTo + "]");
var dateFields = [];
for (var i = 0; i < idsToBindTo.length; i++) {
var dateFieldId = idsToBindTo[i];
var dateField = document.getElementById(dateFieldId);
if (!dateField) {
// field not present, wait
console.log("Date field with id [" + dateFieldId + "] not found, sleeping");
return;
} else {
// field present, add it to the list
console.log("Date field with id [" + dateFieldId + "] found, adding to binding list");
dateFields.push(dateField);
}
}
// all fields present and accounted for, bind the listeners!
clearInterval(timer);
console.log("All fields available, binding focus listeners");
bindTo(dateFields);
}
function bindTo(dateFields) {
// assign focus handlers to all date fields
for (var i = 0; i < dateFields.length; i++) {
addFocusListeners(dateFields[i]);
}
}
function addFocusListeners(dateField) {
// when focusing the date field, click the button
dateField.onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
// or when focusing the date field input, click the button
dateField.getElementsByTagName("input")[0].onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
}
};
4) 结果
Vaadin 小部件既简单又很棒!但它们的可配置性也很差。 我需要我的 DateField 小部件才能在焦点事件上打开日历。我没有在官方 Vaadin documentation. I found some 3rd party widget here 中找到该功能,但它是为 Vaadin 7.7 编译的,我使用最新的 Vaadin (8.0.6)。它还具有 Joda-time 2.1 依赖性,这在我的项目中是非常不受欢迎的。那么,是否有任何简单的方法来调整股票 vaadin DateField 小部件以在字段焦点上打开它的日历,或者我是否需要为此编写自己的组件?任何帮助表示赞赏。
正如我在评论中所说,据我所知,目前该框架不提供以编程方式打开日历弹出窗口的隐式方式。同样的事情也适用于其他一些组件,例如网格编辑器或组合项列表。
我能想到的一个快速解决方法是添加一个 javascript extension 来为所有日期字段注册焦点侦听器,并在日期字段获得焦点时单击按钮。请在下面找到一个示例。
P.S。如果您只需要将此应用于某些日期字段,您可以添加 ID 并将它们传递给 JS,您将在 JS 中执行类似 document.getElementById('myDateFieldId')
而不是 document.getElementsByClassName("v-datefield")
.
1) 组件布局
public class MyDateFieldComponent extends HorizontalLayout {
public MyDateFieldComponent() {
// basic setup
DateField fromDateField = new DateField("From", LocalDate.of(2011, Month.FEBRUARY, 6));
DateField toDateField = new DateField("To", LocalDate.of(2018, Month.FEBRUARY, 6));
setSpacing(true);
addComponents(fromDateField, toDateField);
// add the extension
addExtension(new CalendarFocusPopupOpenerExtension());
}
}
2) 分机 - java/server 边
import com.vaadin.annotations.JavaScript;
import com.vaadin.server.AbstractJavaScriptExtension;
@JavaScript("calendar-focus-popup-opener-extension.js")
public class CalendarFocusPopupOpenerExtension extends AbstractJavaScriptExtension {
public CalendarFocusPopupOpenerExtension() {
// call the bind function defined in the associated JS
callFunction("bind");
}
}
3) 分机 - js/client 边
window.com_example_calendar_CalendarFocusPopupOpenerExtension = function () {
this.bind = function () {
if (document.readyState === "complete") {
// if executed when document already loaded, just bind
console.log("Doc already loaded, binding");
bindToAllDateFields();
} else {
// otherwise, bind when finished loading
console.log("Doc nod loaded, binding later");
window.onload = function () {
console.log("Doc finally loaded, binding");
bindToAllDateFields();
}
}
};
function bindToAllDateFields() {
// get all the date fields to assign focus handlers to
var dateFields = document.getElementsByClassName("v-datefield");
for (var i = 0; i < dateFields.length; i++) {
addFocusListeners(dateFields[i]);
}
}
function addFocusListeners(dateField) {
// when focusing the date field, click the button
dateField.onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
// or when focusing the date field input, click the button
dateField.getElementsByTagName("input")[0].onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
}
};
4) 结果
稍后更新
第二种方法可能是为您的字段分配一些 ID,然后定期检查以查看所有字段何时可见,一旦可见,就绑定焦点侦听器。
1) 组件布局
public class MyDateFieldComponent extends HorizontalLayout {
public MyDateFieldComponent() {
// basic setup
DateField fromDateField = new DateField("From", LocalDate.of(2011, Month.FEBRUARY, 6));
fromDateField.setId("fromDateField"); // use id to bind
fromDateField.setVisible(false); // initially hide it
DateField toDateField = new DateField("To", LocalDate.of(2018, Month.FEBRUARY, 6));
toDateField.setId("toDateField"); // use id to bind
toDateField.setVisible(false); // initially hide it
// simulate a delay until the fields are available
Button showFieldsButton = new Button("Show fields", e -> {
fromDateField.setVisible(true);
toDateField.setVisible(true);
});
setSpacing(true);
addComponents(showFieldsButton, fromDateField, toDateField);
// add the extension
addExtension(new CalendarFocusPopupOpenerExtension(fromDateField.getId(), toDateField.getId()));
}
}
2) 分机 - java/server 边
@JavaScript("calendar-focus-popup-opener-extension.js")
public class CalendarFocusPopupOpenerExtension extends AbstractJavaScriptExtension {
public CalendarFocusPopupOpenerExtension(String... idsToBindTo) {
// send the arguments as an array of strings
JsonArray arguments = Json.createArray();
for (int i = 0; i < idsToBindTo.length; i++) {
arguments.set(i, idsToBindTo[i]);
}
// call the bind defined in the associated JS
callFunction("bind", arguments);
}
}
3) 分机 - js/client 边
window.com_example_calendar_CalendarFocusPopupOpenerExtension = function () {
var timer;
this.bind = function (idsToBindTo) {
// check every second to see if the fields are available. interval can be tweaked as required
timer = setInterval(function () {
bindWhenFieldsAreAvailable(idsToBindTo);
}, 1000);
};
function bindWhenFieldsAreAvailable(idsToBindTo) {
console.log("Looking for the following date field ids: [" + idsToBindTo + "]");
var dateFields = [];
for (var i = 0; i < idsToBindTo.length; i++) {
var dateFieldId = idsToBindTo[i];
var dateField = document.getElementById(dateFieldId);
if (!dateField) {
// field not present, wait
console.log("Date field with id [" + dateFieldId + "] not found, sleeping");
return;
} else {
// field present, add it to the list
console.log("Date field with id [" + dateFieldId + "] found, adding to binding list");
dateFields.push(dateField);
}
}
// all fields present and accounted for, bind the listeners!
clearInterval(timer);
console.log("All fields available, binding focus listeners");
bindTo(dateFields);
}
function bindTo(dateFields) {
// assign focus handlers to all date fields
for (var i = 0; i < dateFields.length; i++) {
addFocusListeners(dateFields[i]);
}
}
function addFocusListeners(dateField) {
// when focusing the date field, click the button
dateField.onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
// or when focusing the date field input, click the button
dateField.getElementsByTagName("input")[0].onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
}
};
4) 结果