How to display current month as text and pass the value? - visualforce

I have tried the second option first without considering your valuable advice but now I have over complicated the idea. I have tried passing the values as a date picker and then split them but that did not help me. I tried the below code and I will explain you the challenge I face now.
// I created a Map to store the values as you specified for different languages.
public map<integer,string> monthmaps(){
map<integer, string> monthMapStatic = new map<integer, string>();
monthMapStatic.put(1, Label.PD_General_Month_Jan);
monthMapStatic.put(2, Label.PD_General_Month_Feb);
monthMapStatic.put(3, Label.PD_General_Month_Mar);
monthMapStatic.put(4, Label.PD_General_Month_Apr);
monthMapStatic.put(5, Label.PD_General_Month_May);
monthMapStatic.put(6, Label.PD_General_Month_Jun);
monthMapStatic.put(7, Label.PD_General_Month_Jul);
monthMapStatic.put(8, Label.PD_General_Month_Aug);
monthMapStatic.put(9, Label.PD_General_Month_Sep);
monthMapStatic.put(10, Label.PD_General_Month_Oct);
monthMapStatic.put(11, Label.PD_General_Month_Nov);
monthMapStatic.put(12, Label.PD_General_Month_Dec);
return monthMapStatic;
}
// Then I ran the below logic but it only runs for current Month.//
for(Integer i=1; i<date.today().month()+1; i++){
this.monthList.add(new SelectOption(String.valueOf(i), monthmaps().get(i)));
}
// I am passing the value as a string to the UI
monthSelection = String.valueOf(date.today().month());
Question: I can't give a Year or I have by default Year passing through, I need past 2 years. Hence the two dropdown option was asked
VF Page:
<apex:selectList value="{!monthSelection}"
multiselect="false" size="1"
styleClass="form-control pull-left monthlyDropDown"
style="height: 33px;">
<apex:selectOptions value="{!monthList}" />
</apex:selectList>
So the question still lies, how can give the option from the Map to the user for selecting Month from previous year.
Here is how they have previously passed the value to string SQL we are trying to pass.
joinQueryMonth += 'AND ((mcc.processing_year__c=\''+ thisMonthDate.year() +'\' AND mcc.processing_month__c=' + thisMonthDate.month() + ') \n';
I hope I am clear this time.

I have considered eyescream first answer and have come up with the following logic
DateTime d = System.now();
for(Integer i = 1; i < 13; ++i){
String label = d.format('MMMM yyyy');
this.monthList.add(new SelectOption(String.valueOf(i), label));
d = d.addMonths(-1);
}
The logic I used to pass it to my SQL query
Integer month_Sel = date.today().month()-(Integer.valueOf(monthSelection)-1);
Integer year_Sel = date.today().year();
if(month_Sel <= 0){
month_Sel = 12+month_Sel;
year_Sel = year_Sel-1;
}
Date thisMonthDate = date.newInstance(year_Sel, month_Sel, 1);
Output for this would be like below
September 2017
August 2017
.
.
October 2016
Now my Query would take the values of year_sel and month_sel and return the year and month selection.
Thanks eyescream for your logic.

The SelectOption function accepts value and label parameters. So you can have more human-friendly label for month but still pass it as a number to Apex.
Here's quite complex demo. See edit history for previous versions & explanation of some of the tricks.
<apex:page controller="StackOverflow45934022">
<apex:form >
<fieldset>
<legend>Single dropdown</legend>
<apex:selectList value="{!monthAndYear}" multiselect="false" size="1">
<apex:selectOptions value="{!monthAndYearOptions}" />
<apex:actionSupport action="{!submitSingle}" event="onchange" reRender="results" />
</apex:selectList>
</fieldset>
<fieldset>
<legend>Two dropdowns</legend>
<apex:selectList value="{!year}" multiselect="false" size="1">
<apex:selectOptions value="{!yearOptions}" />
</apex:selectList>
<apex:selectList value="{!month}" multiselect="false" size="1">
<apex:selectOption itemValue="1" itemLabel="January"/> <!-- You can use itemLabel="{!$Label.PD_General_Month_Jan}" -->
<apex:selectOption itemValue="2" itemLabel="February"/>
<apex:selectOption itemValue="3" itemLabel="March"/>
<apex:selectOption itemValue="11" itemLabel="November"/>
<apex:selectOption itemValue="12" itemLabel="December"/>
</apex:selectList>
<apex:commandButton value="Submit" action="{!submitMultiple}" reRender="results" />
</fieldset>
</apex:form>
<hr/>
<apex:outputPanel id="results">
Month (as integer) : {!m}<br/>
Year : {!y}
</apex:outputPanel>
</apex:page>
public with sharing class StackOverflow45934022{
public Integer m {get;private set;}
public Integer y {get; private set;}
public StackOverflow45934022(){
m = System.today().month();
y = System.today().year();
}
// Single dropdown version start
public String monthAndYear {get;set;}
public List<SelectOption> getMonthAndYearOptions(){
List<SelectOption> ret = new List<SelectOption>();
Date thisMonth = System.today().toStartOfMonth(), januaryLastYear = Date.newInstance(System.today().year() -1, 1, 1);
DateTime d = DateTime.newInstance(thisMonth, Time.newInstance(0,0,0,0));
while(d >= januaryLastYear){
ret.add(new SelectOption(d.format('MM-YYYY'), d.format('MMMM YYYY'))); // you will use your map with month names to build labels
d = d.addMonths(-1);
}
return ret;
}
public void submitSingle(){
if(String.isNotBlank(monthAndYear) && monthAndYear.contains('-')){
List<String> temp = monthAndYear.split('-');
m = Integer.valueOf(temp[0]);
y = Integer.valueOf(temp[1]);
}
}
// Single dropdown version end
public String year {get;set;}
public String month {get; set;}
public List<SelectOption> getYearOptions(){
Date today = System.today();
String y0 = String.valueOf(today.year()), y1 = String.valueOf(today.year() -1);
return new List<SelectOption>{
new SelectOption(y0, y0),
new SelectOption(y1, y1)
};
}
public void submitMultiple(){
m = Integer.valueOf(month);
y = Integer.valueOf(year);
}
}

Related

Spring boot and BigDecimal or Double serialization problem

İ can not handle BigDecimal initialization properly , i have an entity which has a BigDecimal field like this:
#Entity
public class Menu{
...
#Digits(integer=6, fraction=2)
private BigDecimal price;
...
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
...
other generated getters and setters toString etc.
...
}
And in frontend i use thymeleaf, in html form (which adds and updates new menu item) i have this input for Big Decimal value:
<div class="form-group">
<label for="price">Enter Price</label>
<input type="number" class="form-control" step="0.01" id="price" name="price" th:field="*{price}" placeholder="enter Price" value=" ">
</div>
And for restrict the user to enter more than 2 digit precision on price value, i have a js code like this:
$('#price').keypress(function (e) {
var character = String.fromCharCode(e.keyCode)
var newValue = this.value + character;
if (isNaN(newValue) || parseFloat(newValue) * 100 % 1 > 0) {
e.preventDefault();
return false;
}
});
The question is : when user enters 10.25 value in the form , thymeleaf renders it like 10.2499998.. . Even other rest endpoints returns this entity with value in json like 10.249999. But when i looked at my database (postgresql and offcourse i use jpa) this value seems just fine which is 10.25.
So i know when initializing new BigDecimal value the constructor must be like new BigDecimal("10.25") with string in parameter.But all i have is the default getters and setters and my controller is simple post controller for entity saving like this:
#PostMapping("/additem")
public String addItemPost(#ModelAttribute(value="menu") #Valid Menu menu,Model model,BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "addmenuitem";
}
this.menuService.saveMenuItem(menu);
return "redirect:/restaurant/menu";
}
The problem 2 is : I tried to change BigDecimal with Double value and after that, the input form takes value as we suggest and i see that value everywhere correctly.But if i write more digit after comma , the js function blocks me to write more than 2 digit but real value again becomes 10.2499999.. .
It must be something with spring's strategy of taking values from thymeleaf form, and than initialize those values into entity , but i never do that manually neighter couldn't debug it.
So ı don't know the problem is if my javascript function or my input form or the variable type.Please help.
Any help will be appreciated.
I found the problem and writing here if anyone encounter a problem like this.
My Problem was not in localhost , but occured on heroku.So i realized that in heroku postgresql db my BigDecimal columns did not updated and in localhost they were changing whenever i re-run because of jdbc table creation strategy choice.
I made the entity attribute Double and changed remote db columns to double precision than problem solved.

JSF convertDateTime validation error [duplicate]

This question already has an answer here:
"Validation Error: Value is not valid" error from f:datetimeConverter
(1 answer)
Closed 6 years ago.
I have a problem mentioned in the topic. I have
<h:selectOneMenu class="time" id="time" value="#{auctionBean.expDate}">
<f:convertDateTime pattern="dd/MM/yyyy HH:mm:ss"/>
<f:selectItem itemValue="11/11/1111 11:11:11" itemLabel="1 day" />
<f:selectItem itemValue="#{auctionBean.calculateExpDate(4)}" itemLabel="4 days" />
<f:selectItem itemValue="#{auctionBean.calculateExpDate(7)}" itemLabel="7 days" />
<f:selectItem itemValue="#{auctionBean.calculateExpDate(14)}" itemLabel="14 days" />
</h:selectOneMenu>
The problem is i am getting Validation Error: Value is not valid message for all items but first one.
The method:
public String calculateExpDate(int days) {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DATE, days);
Format formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
System.out.println("data: " + formatter.format(cal.getTime()));
return formatter.format(cal.getTime());
}
It returns String in good format. Output from system.out:
INFO: data: 10/10/2013 20:40:04
Where is the problem? I have no clue at all
A good one!
If what you are getting is a VALIDATION error, not a CONVERSION problem, then the probable scenario is:
the list of available values is created, and the values have precision of 1 second,
user picks one of them,
but on postback the available values get recalculated, and they are all a couple of seconds later than the original ones.
so the value that your user picked is no more available on the list of possible values,
and so a validation error happens (which is what JSF does always when the value chosen is no longer on the list of select items).
you do not get it with the first item, because it's the only one that does not change with time :-).
If you move the backing bean to view scope (or session scope), or cut the precision, it should work. Or better yet - make an enum with values of NOW, IN_2_DAYS, IN_4_DAYS and so on. And calculate the real date after the enum is chosen.
fdreger is right! I marked his post as an answer. Thanks:)
This is my solution if you are lazy (however it might be done better I guess):
JSF:
<h:selectOneMenu class="time" id="time" value="#{auctionBean.choosenOption}">
<f:selectItems value="#{auctionBean.days}" var="days" itemValue="#{days}" itemLabel="#{days.label}"/>
</h:selectOneMenu>
fragment of my auctionBean:
public enum Days {
IN_1_DAY("1 dzień", 1),
IN_4_DAYS("4 dni", 4),
IN_7_DAYS("7 dni", 7),
IN_14_DAYS("14 dni", 14);
private String label;
private int days;
private Days(String label, int days) {
this.label = label;
this.days = days;
}
public String getLabel() {
return label;
}
public Date calculateExpDate() {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DATE, this.days);
return cal.getTime();
}
}
private Days choosenOption;
public void setChoosenOption(Days choosenOption) {
this.choosenOption = choosenOption;
expDate = choosenOption.calculateExpDate();
}
public Days getChoosenOption() {
return choosenOption;
}
public Days[] getDays() {
return Days.values();
}
User chooses how many days his auction should be active and i calculate what is an expiration date.
expDate is Date object which i set only once, after choosing the single enum and sumbitting the form. Pretty good solution suggested :)

Get single value from XML and bind it to a textblock?

Trying to create a prayer time app for prayertimes in Oslo. I have a XML file located in the app.
What i want to do:
Based on month and the day, get value for morning prayer, evening prayer and so on.
I want one value at a time, and show it in a textblock. how do i do it?
I am currently getting the info in a listBox but i rather want the single value to be shown in a textblock. Or should i use some other thing?
public class PrayerTime
{
public string Fajr { get; set; }
public string Sunrise { get; set; }
}
To get the value:
XDocument loadedCustomData = XDocument.Load("WimPrayerTime.xml");
var filteredData = from c in loadedCustomData.Descendants("PrayerTime")
where c.Attribute("Day").Value == myDay.Day.ToString()
&& c.Attribute("Moth").Value == myDay.Month.ToString()
select new PrayerTime()
{
Fajr = c.Attribute("Fajr").Value,
Soloppgang = c.Attribute("Soloppgang").Value,
};
listBox1.ItemsSource = filteredData;
Also i want to know how best the XML should be set up for this purpose.
Like this:
<PrayerTime>
<Day>1</Day>
<Month>5</Month>
<Fajr>07:00</Fajr>
<Sunrise>09:00</Sunrise>
</PrayerTime>
Or like this:
<PrayerTime
Day ="1"
Month="5"
Fajr="07:00"
Sunrise="09:00"
/>
yourTextBox.Text = filteredData.First().Fajr;
As to know whether it's best to put information in a XML file as attributes or nodes, that's a recurrent question with no definite answer. In most cases, it's just a matter of taste.

How I can dynamically add a new entity to my Htmlhelper.dropdownlist

I have the following action method that initiated SelectList as follow:-
public PartialViewResult Search(string q, int q2,string q3,string sortOrder)
{
ViewBag.q2 = new SelectList(elearningrepository.FindAllLevels().ToList(), "DifficultyID", "Description", 2);
ViewBag.q3 = new SelectList(elearningrepository.FindAllusers().ToList(), "UserID", "UserID",2);
ViewBag.today = DateTime.Today;
ViewBag.nextmonth = DateTime.Now.AddMonths(1);
var v = elearningrepository.searchquestions3(q, q2, q3);
return PartialView("_searchquestion", v);
}
And the following repository method:-
public IQueryable<Question> searchquestions3(string q, int? q2 , string)
{
return from u in entities1.Questions
where (u.Description.Contains(q) && (u.DifficultyID == q2 || q2 == "Any" ) && ( u.CreatedBy == q3 || q3 == "Any"))
select u;}
then on the view i render the drop down list as follow:-
<th>
#Html.DropDownList("q2")
</th>
</tr>
<tr>
<th>
Seach By Create By:-
</th>
<th>
#Html.DropDownList("q3")
</th>
But how i can add a new value that represents “Any” word to the q2 & q3 drop down lists, so that the repository method will work as intended ?
BR
First of all I would advice you to use ViewModels when you work with more complex objects. You can achieve it with the ViewBag of course, but it's messy.
Now. In the action you can do:
var list = elearningrepository.FindAllLevels().ToList()
list.InsertAt(0, new TypeOfYourObject() {ValueProperty = "Any"});
ViewBag.q2 = new SelectList(list, "DifficultyID", "Description", 2);
You can do adequatly with the others, but seriously think about strongly typed ViewModel.
#Html.DropDownList("q3","Any")
You need to use the optionLabel
in your controller that you get your post.
Whatever you want to then do, example. a database transaction, do only if the value == empty string or label == "Any"
Client side solution with Jquery
$("#Select_Id").append("<option value='0'>Text</option>");
You can use .prepend() if you want to add it as first element.

DropDown list with translated values

I have enums in my domain like this
public enum AdTypeEnum { Sale = 1, Rent = 2, SaleOrRent = 3 };
In my view I'm rendering this enums like this
<div class="editor-field">
#Html.DropDownListFor(x => x.AdType, new SelectList(Enum.GetValues(typeof(MyDomain.Domain.Property.AdTypeEnum))))
</div>
Now, what I'm trying to achive is based on selected language I want to display these enums in drop down list in selected language.
Did you try something like:
public static Array Localize(Array values)
{
string[] result = new string[values.Length];
for (int i = 0; i < values.Length; ++i)
result[i] = Resources.ResourceManager.GetString(values.GetValue(i).ToString());
return result;
}
A better implementation should use a different key-set for each enum type (using the enum name as part of the GetString() parameter).
Anyway this method is pretty naive, I think for a big application (or for more complex scenarios) you may need to inherit from SelectList class.

Resources