I am practicing using ajax jsf and I have the following code to build the view.
<f:view contentType="text/html;charset=UTF-8" encoding="UTF-8">
<h:head>
<title>Advances Ajax Effect</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</h:head>
<h:body>
<h1>Advanced</h1>
<h:form>
<h:messages id="msgs" class="msgs" showDetail="true" globalOnly="true"/>
<h:panelGrid columns="2" cellspacing="7">
<h:outputLabel for="country" value="Country"/>
<h:selectOneMenu id="country" value="#{basicView.country}" style="width: 12rem;">
<f:ajax event="change" execute="@this" render="city" listener="#{basicView.onChangeCountry}"/>
<f:selectItem itemLabel="--Select Country--" itemValue="" noSelectionOption="true"/>
<f:selectItems value="#{basicView.countries}"/>
</h:selectOneMenu>
<h:outputLabel for="city" value="City"/>
<h:selectOneMenu id="city" value="#{basicView.city}" style="width: 12rem;">
<f:selectItem itemLabel="--Select City--" itemValue="" noSelectionOption="true"/>
<f:selectItems value="#{basicView.cities}"/>
</h:selectOneMenu>
</h:panelGrid>
<h:commandButton value="Submit">
<f:ajax execute="city" render="msgs" listener="#{basicView.displayLocation}"/>
</h:commandButton>
</h:form>
</h:body>
</f:view>
The goal of this code is simple; I am only dynamically and asynchronously filling the content of a selectOneMenu depending on the country that is chosen in the previous selectOneMenu. For example: if the user selects the USA country, the City Menu will be filled automatically with a list of cities belonging to the USA, the same happens if he chooses Germany or Brazil. Once the country and city have been selected, pressing the submit button displays a global message to the user confirming their choice.
as shown in the picture above I also attach the code of the backing bean
public class BasicView {
private String country;
private String city;
private Map<String, String> countries;
private Map<String, String> cities;
private Map<String, Map<String, String>> data;
public BasicView(){}
@PostConstruct
public void init(){
countries = new HashMap<>();
cities = new HashMap<>();
data = new HashMap<>();
countries.put("USA", "USA");
countries.put("Germany", "Germany");
countries.put("Brazil", "Brazil");
Map<String, String> map = new HashMap<>();
map.put("San Francisco", "San Francisco");
map.put("New York", "New york");
map.put("Denver", "Denver");
//USA cities added
data.put("USA", map);
map = new HashMap<>();
map.put("Frankfurt", "Frankfurt");
map.put("Berlin", "Berlin");
map.put("Munich", "Munich");
//Germany cities added
data.put("Germany", map);
map = new HashMap<>();
map.put("Sao Paulo", "Sao Paulo");
map.put("Rio de Janeiro", "Rio de Janeiro");
map.put("Salvador", "Salvador");
//Brazil cities added
data.put("Brazil", map);
}
public void onChangeCountry(AjaxBehaviorEvent event){
if(country != null && !country.equals("")){
cities = data.get(country);
}
}
public void displayLocation(AjaxBehaviorEvent event){
FacesMessage msg;
if(country != null && city != null){
msg = new FacesMessage("Selected", city + " of " + country);
//add styles to the component that will display the aproval message
}
else{
msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid", "City is not Selected.");
//add styles to the component that will display the error message
}
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Map<String, String> getCountries() {
return countries;
}
public void setCountries(Map<String, String> countries) {
this.countries = countries;
}
public Map<String, String> getCities() {
return cities;
}
public void setCities(Map<String, String> cities) {
this.cities = cities;
}
public Map<String, Map<String, String>> getData() {
return data;
}
public void setData(Map<String, Map<String, String>> data) {
this.data = data;
}
}
What I'm looking to do is that when the displayLocation method is executed and the message that the user will see is created, I can somehow modify the classes of my <h: messages> component. If the message is confirmation, add the confirmation class "<h: messages class = 'confirm'>" to the component, but if the message is an error message, you can add the error class "<h: message class =" error "> and in this way to be able to assign a specific style for each particular message.
Does anyone know the way to be able to modify the attributes of any component in jsf from a backing bean? I appreciate any help