У меня есть простой указатель даты в модальном диалоге. Установка начальной даты с шаблоном " ММММ гггг " (немецкий) работает отлично. Когда я пытаюсь обновить компонент с помощью вызова ajax, я получаю исключение javascript "uncaught name at positon [...]".
Я использую Primefaces 7.0 и сам написал конвертер года в месяц.
Язык PrimeFaces:
PrimeFaces.locales['de'] = {
closeText: 'Schließen',
prevText: 'Zurück',
nextText: 'Weiter',
monthNames: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
monthNamesShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
dayNames: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
dayNamesShort: ['Son', 'Mon', 'Die', 'Mit', 'Don', 'Fre', 'Sam'],
dayNamesMin: ['S', 'M', 'D', 'M ', 'D', 'F ', 'S'],
weekHeader: 'Woche',
firstDay: 1,
isRTL: false,
showMonthAfterYear: false,
yearSuffix: '',
timeOnlyTitle: 'Nur Zeit',
timeText: 'Zeit',
hourText: 'Stunde',
minuteText: 'Minute',
secondText: 'Sekunde',
currentText: 'Aktuelles Datum',
ampm: false,
month: 'Monat',
week: 'Woche',
day: 'Tag',
allDayText: 'Ganzer Tag',
};
Преобразователь:
/**
* The Class YearMonthConverter.
*/
@Slf4j
@SuppressWarnings("common-java:DuplicatedBlocks")
@FacesConverter(value = "yearMonthConverter")
public class YearMonthConverter implements Converter {
private static final String PATTERN = "MMMM yyyy";
@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
String componentPattern = extractPattern(uiComponent);
String pattern = componentPattern.equals("") ? PATTERN : componentPattern;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, Locale.GERMANY);
try {
return YearMonth.parse(s, formatter);
} catch (DateTimeParseException e) {
log.warn("conversion of date '{}' expected pattern '{}' failed with {}", s, pattern, e);
return YearMonth.now();
}
}
@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) {
if (o instanceof YearMonth) {
String componentPattern = extractPattern(uiComponent);
String pattern = componentPattern.equals("") ? PATTERN : componentPattern;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, Locale.GERMANY);
return formatter.format((YearMonth) o);
} else {
return null;
}
}
private String extractPattern(UIComponent component) {
// try to get the pattern from component
if (component instanceof Calendar) {
Calendar calendarComponent = (Calendar) component;
return calendarComponent.getPattern();
} else if (component instanceof DatePicker) {
DatePicker datepickerComponent = (DatePicker) component;
return datepickerComponent.getPattern();
}
return "";
}
}
Пример xhtml-файла:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<composite:interface>
</composite:interface>
<composite:implementation>
<style type="text/css">
.ui-panel .ui-panel-content {
padding: 0;
}
</style>
<!-- modaler someDialog -->
<p:dialog id="someDialog"
header="some header"
widgetVar="someDlg"
modal="true"
width="500"
height="280"
resizable="false"
closeOnEscape="true">
<p:panel id="pnlContent" styleClass="ui-noborder">
<p:panelGrid id="inputArea" columns="2">
<p:outputLabel value="Label:" style="width: 12em; display: block;"/>
<p:outputLabel value="example"
style="display: block;"/>
<p:outputLabel value="Monat:" style="width: 12em; display: block;"/>
<h:panelGroup>
<!-- Monat zurück -->
<p:commandButton
id="btnPrevMonth"
action="#{someDialogVC.previousMonth}"
style="padding: 2px"
icon="fa fa-angle-double-left"/>
<!-- Monatsanzeige -->
<p:datePicker id="dpMonat" view="month"
value="#{someDialogVC.state.selektierterMonat}"
converter="yearMonthConverter" pattern="MMMM yyyy" yearNavigator="true"
yearRange="2000:2050" inputStyle="width: 17em;" readonlyInput="true">
<p:ajax event="dateSelect" listener="#{someDialogVC.monthChanged}"/>
</p:datePicker>
<!-- Monat vor -->
<p:commandButton
id="btnNextMonth"
action="#{someDialogVC.nextMonth}"
style="padding: 2px"
icon="fa fa-angle-double-right"/>
</h:panelGroup>
</p:panelGrid>
<p:separator style="border-color: #aaaaaa; margin-bottom: 10px;"/>
<div style="display: flex; justify-content: flex-end">
<p:commandButton id="btnCreate"
value="Anlegen"
action="#{someDialogVC.createAndExit()}"
disabled="#{someDialogVC.doGetAnlegenDisabled()}"/>
</div>
</p:panel>
<p:blockUI block="pnlContent" trigger="btnCreate">
<p:graphicImage name="images/loader.gif"/>
</p:blockUI>
</p:dialog>
</composite:implementation>
</html>
установка начальной даты в бобе:
@PostConstruct
public void init() {
data = new someDialogVO();
state = new someDialogVS();
state.setSelektierterMonat(YearMonth.now());
}
код фрагмента bean:
public void previousMonth() {
state.setSelektierterMonat(state.getSelektierterMonat().minusMonths(1L));
updateMonat();
}
public void nextMonth() {
state.setSelektierterMonat(state.getSelektierterMonat().plusMonths(1L));
updateMonat();
}
private void updateMonat() {
PrimeFaces.current().ajax().update("contentForm:someDialog:dpMonat");
}
После вызова обновления ajax я вижу, что новый месяц выбирается визуально, но через несколько миллисекунд я получаю описанное исключение javascript. При использовании шаблона " MM.yyyy " все работает нормально.