primefaces calendar component is getting Date by default. Can I get only month and year without dates.
How to get only month and year
primefaces calendar component is getting Date by default. Can I get only month and year without dates.
How to get only month and year
I just hid the table of the day picker with CSS. I also had to create my own arrows for navigating, because the standard arrows do not fire the dateSelect
event.
Markup:
<p:commandButton actionListener="#{bean.decrementMonth}"
id="navLeft" update="[your components]" icon="ui-icon-triangle-1-w" />
<h:panelGroup class="tableView">
<p:calendar value="#{bean.selectedDate}" mode="inline" />
</h:panelGroup>
<p:commandButton actionListener="#{bean.incrementMonth}"
id="navRight" update="[your components]" icon="ui-icon-triangle-1-e" />
CSS:
.tableView table,
.tableView a.ui-datepicker-prev,
.tableView a.ui-datepicker-next {
display: none;
}
Bean methods:
public void decrementMonth() throws Exception {
Calendar c = Calendar.getInstance();
c.setTime(this.selectedDate);
c.add(Calendar.MONTH, -1);
//... business logic to update date dependent data
}
public void incrementMonth() throws Exception {
Calendar c = Calendar.getInstance();
c.setTime(this.selectedDate);
c.add(Calendar.MONTH, 1);
//... business logic to update date dependent data
}
Result (PrimeFaces 3.4.2):
PrimeFaces don't have month year picker component as such. So if you want to use jQuery based external component then checkout jQuery.mtz.monthpicker
Here is how I achieved a simple month's range selector which look like this :
The VoirCalendrier.xhtml web page :
<h:form id="calendrierRegenererFormulaire">
<h2><h:outputText value="#{msgs.CalendrierPlageAafficher} "/></h2>
<h:panelGrid columns="6">
<h:outputLabel value="#{msgs.CalendrierDateDebut} : " for="calendrierDateDebut" />
<p:calendar id="calendrierDateDebut" value="#{locationsControleur.dateDebut}"
pattern="yyyy-MM-dd" effect="slideDown" navigator="true" mode="inline"
lang="#{sessionControleur.localeInterface}" locale="#{sessionControleur.langue}" style="moisAnSeul" />
<h:outputLabel value="#{msgs.CalendrierDateFin} : " for="calendrierDateFin" />
<p:calendar id="calendrierDateFin" value="#{locationsControleur.dateFin}"
pattern="yyyy-MM-dd" effect="slideDown" navigator="true" mode="inline"
lang="#{sessionControleur.localeInterface}" locale="#{sessionControleur.langue}" style="moisAnSeul" />
<p:commandButton value="#{msgs.CalendrierRegenerer}" update=":calendrierFormulaire"
onclick="regenererCal()"/>
</h:panelGrid>
</h:form>
To prevent the display of the calendar days, you just have to set its dislay property to none with the following code in your active css file :
.ui-datepicker-calendar {
display: none;
}
As noted by Daniel Slazlay above, navigating with the month/year drop downs or with the arrow icons do not change the internal date value of the p:calendar controls. To achieve this, the value of the selected month and year drop downs are read for the two p:calendar when the «regenerate calendar» button is fired. With this information, you are able to construct a date string with the format "yyyy-MM-dd" and to set the internal hidden value of the p:calendar controls For the starting month of the month range, the first day of the month is returned while for the ending month, it is the last day of the month which is returned. This is done with the followin javascript :
function regenererCal() {
year = $("#calendrierRegenererFormulaire\\:calendrierDateDebut .ui-datepicker-year").val();
month = $("#calendrierRegenererFormulaire\\:calendrierDateDebut .ui-datepicker-month").val();
$('#calendrierRegenererFormulaire\\:calendrierDateDebut_input').val(year + '-' + ('0' + (++month)).slice(-2) + '-01');
year = $("#calendrierRegenererFormulaire\\:calendrierDateFin .ui-datepicker-year").val();
month = $("#calendrierRegenererFormulaire\\:calendrierDateFin .ui-datepicker-month").val();
lastDay = new Date(year, month + 1, 0); // To get last day of month, see http://stackoverflow.com/a/13572682/1431979
$('#calendrierRegenererFormulaire\\:calendrierDateFin_input').val(lastDay.getFullYear() + '-' + ('0' + (lastDay.getMonth()+1)).slice(-2) + '-' + lastDay.getDate());
// Check what is posted to your server
console.log("[voirCalendrier.js]regenererCal calendrierDateDebut_input = " + $('#calendrierRegenererFormulaire\\:calendrierDateDebut_input').val());
console.log("[voirCalendrier.js]regenererCal calendrierDateFin_input = " + $('#calendrierRegenererFormulaire\\:calendrierDateFin_input').val());
}
On the server side, you can check that the right information is received by the setter methods :
...
formatAAAA_MM_JJ = new SimpleDateFormat("yyyy-MM-dd HH:mm", langue);
...
public void setDateDebut(Date dateDebut) {
this.dateDebut = dateDebut;
logger.info("{locationsContrôleur}setDateDebut dateDebut = " + formatAAAA_MM_JJ.format(dateDebut));
}
public void setDateFin(Date dateFin) {
this.dateFin = dateFin;
logger.info("{locationsContrôleur}setDateFin dateFin = " + formatAAAA_MM_JJ.format(dateFin));
}
I hope that this can help others.
The last release of Primefaces (Version 7.0) has just added what you need: the <p:datePicker />
.
It works almost exactly as a <p:calendar>
but it can be easily configured to show only months and years:
<p:datePicker value="#{managedBean.date}" view="month"
pattern="MM/yyyy" yearNavigator="true" yearRange="1986:2025" />
For example, when a month is selected, its value is stored in a "Date" object, which will have the value:
(If April of 2019 is selected) Mon Apr 01 00:00:00 BRT 2019
In this case, you would just have to ignore the day, hour, minute, etc values and use the month and year selected.
For more information, read the Documentation and see the Showcase
//<![CDATA[
function showMonthYear(calendar){
$('.ui-datepicker-calendar').css('display','none');
$('.ui-datepicker').css('top', $('.ui-datepicker').offset().top+250);
var month = '';
var year = '';
if($(calendar).val()){
month = $(calendar).val().split('/')[0];
year = $(calendar).val().split('/')[1];
} else {
month = $.datepicker.formatDate("mm", new Date());
year = $.datepicker.formatDate("yy", new Date());
}
var exists = 0 != $('.ui-datepicker-year option[value='+year+']').length;
if(!exists){
$(".ui-datepicker-year").empty();
var initYear = parseInt(year)-10;
var endYear = parseInt(year)+10;
while(initYear < endYear){
$(".ui-datepicker-year").append($('<option>', {value:initYear, text: initYear}));
initYear++;
}
}
$('.ui-datepicker-month').val(parseInt(month)-1);
$('.ui-datepicker-year').val(year);
$(".ui-datepicker-month").change( function(){changeMonthYear(calendar);});
$(".ui-datepicker-year").change( function(){changeMonthYear(calendar);});
}
function changeMonthYear(calendar){
console.log('changeMonthYear');
$('.ui-datepicker-calendar').css('display','none');
$(".ui-datepicker-month").change( function(){changeMonthYear(calendar);});
$(".ui-datepicker-year").change( function(){changeMonthYear(calendar);});
var month = parseInt($('.ui-datepicker-month').val())+1;
if(month < 10){ month = '0'+month; }
$(calendar).val(month+"/"+parseInt($('.ui-datepicker-year').val()));
}
// ]]>
</script>
<p:calendar size="5"
onclick="showMonthYear(this)"
maxlength="10" pattern="MM/yyyy" navigator="true" />
You can set this in the pattern, in your case it would be:
<p:calendar id="test" value="#{bean.date}" pattern="MM.yyyy" />
I was reading and you cant achieve this functionality out from the box from Primefaces.
https://code.google.com/p/primefaces/issues/detail?id=3453
The question is old but the latest comments from one month ago. So they use this approach:
jQuery UI DatePicker to show month year only
There is also the solution to only use <p:selectOneMenu>
and bild what you need out of it.
Cheers
You could use the viewChange event on the p:calendar to capture the click on the next/previous month. Then you could trigger the dateSelect event by clicking the first day of the month.
JSF:
<p:calendar value="#{sampleBean.month}" styleClass="monthcal" mode="inline">
<p:ajax event="viewChange" onsuccess="$('.ui-calendar[id=\''+this.source+'\'] a.ui-state-default').filter(function(){return $(this).text()*1===1;}).click();" />
</p:calendar>
To hide the pane with days, add the following to the css
.monthcal .ui-datepicker-calendar {display: none;}
Utilized this feature from the Primefaces Documentation:
Another handy event is the viewChange that is fired when month and year changes. An instance of org.primefaces.event.DateViewChangeEvent is passed to the event listener providing the current month and year information.
Made the following code: XHTML
<p:panelGrid styleClass="monthYearOnly">
<p:row>
<p:column>FROM:</p:column>
<p:column>
<p:calendar id="from" mode="inline" value="#{callEntryBean.from}" navigator="true">
<p:ajax event="viewChange" listener="#{callEntryBean.updateFrom()}"/>
</p:calendar>
</p:column>
<p:column>TO:</p:column>
<p:column>
<p:calendar id="to" mode="inline" value="#{callEntryBean.to}" navigator="true">
<p:ajax event="viewChange" listener="#{callEntryBean.updateTo()}"/>
</p:calendar>
</p:column>
<p:column>
<p:commandButton value="Filter"
action="#{callEntryBean.filterDisplay}" update=""/>
</p:column>
</p:row>
</p:panelGrid>
CSS
.monthYearOnly .ui-datepicker-calendar{
display: none;
}
Bean
public void updateFrom(){
Map<String,String> requestParams = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
LOGGER.info("before: " + from);
Calendar c = Calendar.getInstance();
c.setTime(from);
c.set(Calendar.MONTH, Integer.parseInt(requestParams.get("form:from_month")) - 1);
c.set(Calendar.YEAR, Integer.parseInt(requestParams.get("form:from_year")));
from = c.getTime();
LOGGER.info("after: " + from);
}
public void updateTo(){
Map<String,String> requestParams = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
LOGGER.info("before: " + to);
Calendar c = Calendar.getInstance();
c.setTime(to);
c.set(Calendar.MONTH, Integer.parseInt(requestParams.get("form:to_month")) - 1);
c.set(Calendar.YEAR, Integer.parseInt(requestParams.get("form:to_year")));
c.set(Calendar.DATE,c.getActualMaximum(Calendar.DAY_OF_MONTH));
to = c.getTime();
Calendar now = Calendar.getInstance();
if(c.after(now)){
to = now.getTime();
}
LOGGER.info("after: " + to);
}
Basically the ajax trigger when month
or year
is changed is the main feature here. Unfortunately, this is a bit of a work around since I can't retrieve the org.primefaces.event.DateViewChangeEvent
. This seems to be a bug and I posted a report on the Primefaces Forum just now. Will update this post when I get some feedback there.
Hope it helps.
Now the primeng calendar have a month picker option, in the p-calendar using month as view option.
<p-calendar [(ngModel)]="dateValue" view="month" dateFormat="mm/yy" [yearNavigator]="true" yearRange="2000:2030"></p-calendar>
You could do in this way:
XHTML
<p:column>
<p:calendar id="data" locale="pt_BR" navigator="true" showOn="button"
pattern="yyyy-MM-dd" mode="inline" view="month"
maxdate="#{cadastroResumoPorUnidadeBean.dataAtual}"
styleClass="escolha-data"
value="#{cadastroResumoPorUnidadeBean.dataInicio}">
<p:ajax event="viewChange" process="@this"
listener="#{cadastroResumoPorUnidadeBean.onChangeDataInicio}"
update="calendario"/>
</p:calendar>
</p:column>
CSS
.ui-datepicker-calendar {
display: none;
}
BEAN
public void onChangeDataInicio(DateViewChangeEvent event) throws ParseException {
dataInicio = new Date();
SimpleDateFormat dateformat = new SimpleDateFormat("dd-M-yyyy");
String inicio = "01-"+event.getMonth() +"-" + event.getYear();
this.dataInicio = dateformat.parse(inicio);
}
It worked to me!