ClockPicker is a highly configurable component to integrate time inputs (hours / minutes) in a convenient way. Based on clockpicker by weareoutman.
A 12 hour picker with auto-close, a 24 hour picker with manual close and AJAX, and a picker inside a dialog.
ClockPicker in 12-hour mode with a midnight value (12:00 AM). Open the picker and verify that the AM indicator is preserved.
The placement attribute controls which direction the popover opens: top, bottom, left, or right.
The align attribute controls which edge of the popover aligns with the input. For placement="top" or "bottom" use left (default), center or right. For placement="left" or "right" use top or bottom.
<style>
.placement-demo-grid {
display: flex;
flex-wrap: wrap;
gap: 2rem;
}
</style>
<div class="card">
<h5>Basic Usage</h5>
<p>A 12 hour picker with auto-close, a 24 hour picker with manual close and AJAX, and a picker inside a dialog.</p>
<h:form id="formBasicUsage">
<p:growl id="growl" showDetail="true" showSummary="true"/>
<h:panelGroup id="timePickerGroup" layout="block">
<p>AM/PM with Auto-Close</p>
<pe:clockpicker id="autoclose" widgetVar="autocloseWidget" autoClose="true" value="#{clockPickerController.time}"
twelveHour="true" locale="es"/>
<p>24 Hour with Manual Close Mode</p>
<pe:clockpicker id="closeable" widgetVar="closeableWidget" autoClose="false" value="#{clockPickerController.time2}" showOn="button">
<p:ajax listener="#{clockPickerController.showTime2}" update="growl"/>
</pe:clockpicker>
<p>Open In Dialog</p>
<p:commandButton value="Open Dialog" type="button" icon="pi pi-external-link" onclick="PF('dlg1').show()"/>
<p:dialog header="ClockPicker" widgetVar="dlg1" height="350" width="350" showEffect="fade" closeOnEscape="true">
<pe:clockpicker id="dlgClockPicker" widgetVar="dialogClockPickerWidget" autoClose="false" value="#{clockPickerController.time3}" showOn="button">
<p:ajax listener="#{clockPickerController.showTime3}" update="growl"/>
</pe:clockpicker>
</p:dialog>
</h:panelGroup>
<p:commandButton type="button" value="Disable clock pickers" styleClass="mt-2 mr-2"
onclick="PF('autocloseWidget').disable();PF('closeableWidget').disable();"/>
<p:commandButton type="button" value="Enable clock pickers" styleClass="mt-2 mr-2"
onclick="PF('autocloseWidget').enable();PF('closeableWidget').enable();"/>
<p:commandButton id="submitButton" value="Submit" actionListener="#{clockPickerController.showTime1}" update="timePickerGroup growl"
styleClass="mt-2 mr-2" icon="pi pi-save"/>
</h:form>
</div>
<div class="card">
<h5>12 Hour with Midnight Value</h5>
<p>ClockPicker in 12-hour mode with a midnight value (12:00 AM). Open the picker and verify that the AM indicator is preserved.</p>
<h:form id="formMidnightUsage">
<p:growl id="midnightGrowl" showDetail="true" showSummary="true"/>
<h:panelGroup id="timePickerGroup" layout="block">
<p>12 Hour with Midnight Value (12:00 AM)</p>
<pe:clockpicker id="midnight" widgetVar="midnightWidget" autoClose="false"
value="#{clockPickerMidnightController.time}" twelveHour="true" showOn="button"/>
<h:panelGroup id="messagePanel">
<h:outputText value="#{clockPickerMidnightController.message}" styleClass="p-message-info"
rendered="#{not empty clockPickerMidnightController.message}"/>
</h:panelGroup>
</h:panelGroup>
<p:commandButton id="submitButton" value="Submit" action="#{clockPickerMidnightController.submit}"
update="timePickerGroup midnightGrowl" styleClass="mt-2 mr-2" icon="pi pi-save"/>
</h:form>
</div>
<div class="card">
<h5>Placement</h5>
<p>The <code>placement</code> attribute controls which direction the popover opens: top, bottom, left, or right.</p>
<h:form id="formPlacementUsage">
<h:panelGroup id="placementGrid" layout="block" styleClass="placement-demo-grid">
<h:panelGroup layout="block" styleClass="placement-cell">
<p>Top</p>
<pe:clockpicker id="placementTop" widgetVar="placementTopWidget" autoClose="false"
value="#{clockPickerPlacementController.timeTop}" showOn="button" locale="en"
placement="top"/>
</h:panelGroup>
<h:panelGroup layout="block" styleClass="placement-cell">
<p>Bottom</p>
<pe:clockpicker id="placementBottom" widgetVar="placementBottomWidget" autoClose="false"
value="#{clockPickerPlacementController.timeBottom}" showOn="button" locale="en"
placement="bottom"/>
</h:panelGroup>
<h:panelGroup layout="block" styleClass="placement-cell">
<p>Left</p>
<pe:clockpicker id="placementLeft" widgetVar="placementLeftWidget" autoClose="false"
value="#{clockPickerPlacementController.timeLeft}" showOn="button" locale="en"
placement="left"/>
</h:panelGroup>
<h:panelGroup layout="block" styleClass="placement-cell">
<p>Right</p>
<pe:clockpicker id="placementRight" widgetVar="placementRightWidget" autoClose="false"
value="#{clockPickerPlacementController.timeRight}" showOn="button" locale="en"
placement="right"/>
</h:panelGroup>
</h:panelGroup>
</h:form>
</div>
<div class="card">
<h5>Align</h5>
<p>The <code>align</code> attribute controls which edge of the popover aligns with the input. For <code>placement="top"</code> or <code>"bottom"</code> use <code>left</code> (default), <code>center</code> or <code>right</code>. For <code>placement="left"</code> or <code>"right"</code> use <code>top</code> or <code>bottom</code>.</p>
<h:form id="formAlignUsage">
<h:panelGroup id="alignGrid" layout="block" styleClass="placement-demo-grid">
<h:panelGroup layout="block" styleClass="placement-cell">
<p>Left (default)</p>
<pe:clockpicker id="alignLeft" widgetVar="alignLeftWidget" autoClose="false"
value="#{clockPickerAlignController.timeLeft}" showOn="button" locale="en"
align="left" placement="bottom"/>
</h:panelGroup>
<h:panelGroup layout="block" styleClass="placement-cell">
<p>Center</p>
<pe:clockpicker id="alignCenter" widgetVar="alignCenterWidget" autoClose="false"
value="#{clockPickerAlignController.timeCenter}" showOn="button" locale="en"
align="center" placement="bottom"/>
</h:panelGroup>
<h:panelGroup layout="block" styleClass="placement-cell">
<p>Right</p>
<pe:clockpicker id="alignRight" widgetVar="alignRightWidget" autoClose="false"
value="#{clockPickerAlignController.timeRight}" showOn="button" locale="en"
align="right" placement="bottom"/>
</h:panelGroup>
<h:panelGroup layout="block" styleClass="placement-cell">
<p>Top</p>
<pe:clockpicker id="alignTop" widgetVar="alignTopWidget" autoClose="false"
value="#{clockPickerAlignController.timeTop}" showOn="button" locale="en"
align="top" placement="right"/>
</h:panelGroup>
<h:panelGroup layout="block" styleClass="placement-cell">
<p>Bottom</p>
<pe:clockpicker id="alignBottom" widgetVar="alignBottomWidget" autoClose="false"
value="#{clockPickerAlignController.timeBottom}" showOn="button" locale="en"
align="bottom" placement="right"/>
</h:panelGroup>
</h:panelGroup>
</h:form>
</div>
package org.primefaces.extensions.showcase.controller;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalTime;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
/**
* ClockPickerController
*
* @author @jxmai / last modified by $Author$
* @version $Revision$
*/
@Named
@ViewScoped
public class ClockPickerController implements Serializable {
@Serial
private static final long serialVersionUID = 897540091000342926L;
private LocalTime time;
private LocalTime time2;
private LocalTime time3;
public ClockPickerController() {
// Initialize time to 8:15 AM
time = LocalTime.of(8, 15);
time2 = LocalTime.of(9, 28);
time3 = LocalTime.of(13, 44);
}
public void showTime1() {
if (time != null) {
int hour = time.getHour();
int min = time.getMinute();
String message = String.format("Selected hour: %d, Selected min: %d", hour, min);
addMessage(FacesMessage.SEVERITY_INFO, "Info Message", message);
}
else {
addMessage(FacesMessage.SEVERITY_ERROR, "Error Message", "Time is not selected.");
}
}
public void showTime2() {
if (time2 != null) {
addMessage(FacesMessage.SEVERITY_INFO, "Info Message", String.format("Ajax Event: %s", time2));
}
else {
addMessage(FacesMessage.SEVERITY_ERROR, "Error Message", "Time is not selected.");
}
}
public void showTime3() {
if (time3 != null) {
addMessage(FacesMessage.SEVERITY_INFO, "Info Message", String.format("Ajax Event: %s", time3));
}
else {
addMessage(FacesMessage.SEVERITY_ERROR, "Error Message", "Time is not selected.");
}
}
private void addMessage(FacesMessage.Severity severity, String summary, String detail) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, summary, detail));
}
public LocalTime getTime() {
return time;
}
public void setTime(LocalTime time) {
this.time = time;
}
public LocalTime getTime2() {
return time2;
}
public void setTime2(LocalTime time2) {
this.time2 = time2;
}
public LocalTime getTime3() {
return time3;
}
public void setTime3(LocalTime time3) {
this.time3 = time3;
}
}
package org.primefaces.extensions.showcase.controller;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalTime;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
@Named
@ViewScoped
public class ClockPickerMidnightController implements Serializable {
@Serial
private static final long serialVersionUID = 897540091000342926L;
private LocalTime time;
private String message;
public ClockPickerMidnightController() {
time = LocalTime.MIDNIGHT;
}
public String submit() {
message = String.format("Submitted value: %s (hour=%d, min=%d)", time, time.getHour(), time.getMinute());
return null;
}
public String getMessage() {
return message;
}
public LocalTime getTime() {
return time;
}
public void setTime(LocalTime time) {
this.time = time;
}
}
package org.primefaces.extensions.showcase.controller;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalTime;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
@Named
@ViewScoped
public class ClockPickerPlacementController implements Serializable {
@Serial
private static final long serialVersionUID = 897540091000342926L;
private LocalTime timeTop;
private LocalTime timeBottom;
private LocalTime timeLeft;
private LocalTime timeRight;
public ClockPickerPlacementController() {
timeTop = LocalTime.of(9, 0);
timeBottom = LocalTime.of(12, 0);
timeLeft = LocalTime.of(15, 30);
timeRight = LocalTime.of(18, 45);
}
public LocalTime getTimeTop() {
return timeTop;
}
public void setTimeTop(LocalTime timeTop) {
this.timeTop = timeTop;
}
public LocalTime getTimeBottom() {
return timeBottom;
}
public void setTimeBottom(LocalTime timeBottom) {
this.timeBottom = timeBottom;
}
public LocalTime getTimeLeft() {
return timeLeft;
}
public void setTimeLeft(LocalTime timeLeft) {
this.timeLeft = timeLeft;
}
public LocalTime getTimeRight() {
return timeRight;
}
public void setTimeRight(LocalTime timeRight) {
this.timeRight = timeRight;
}
}
package org.primefaces.extensions.showcase.controller;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalTime;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
@Named
@ViewScoped
public class ClockPickerAlignController implements Serializable {
@Serial
private static final long serialVersionUID = 897540091000342926L;
private LocalTime timeLeft;
private LocalTime timeCenter;
private LocalTime timeRight;
private LocalTime timeTop;
private LocalTime timeBottom;
public ClockPickerAlignController() {
timeLeft = LocalTime.of(9, 0);
timeCenter = LocalTime.of(12, 0);
timeRight = LocalTime.of(15, 30);
timeTop = LocalTime.of(18, 45);
timeBottom = LocalTime.of(10, 0);
}
public LocalTime getTimeLeft() {
return timeLeft;
}
public void setTimeLeft(LocalTime timeLeft) {
this.timeLeft = timeLeft;
}
public LocalTime getTimeCenter() {
return timeCenter;
}
public void setTimeCenter(LocalTime timeCenter) {
this.timeCenter = timeCenter;
}
public LocalTime getTimeRight() {
return timeRight;
}
public void setTimeRight(LocalTime timeRight) {
this.timeRight = timeRight;
}
public LocalTime getTimeTop() {
return timeTop;
}
public void setTimeTop(LocalTime timeTop) {
this.timeTop = timeTop;
}
public LocalTime getTimeBottom() {
return timeBottom;
}
public void setTimeBottom(LocalTime timeBottom) {
this.timeBottom = timeBottom;
}
}