SelectOneMenu is used to choose a single item from a list.
<div class="card">
    <h:form>
        <div class="ui-fluid formgrid grid">
            <div class="field col-12 md:col-4">
                <p:outputLabel for="@next" value="Basic"/>
                <p:selectOneMenu id="option" value="#{selectOneMenuView.selectedOption}">
                    <f:selectItem itemLabel="Select One" itemValue=""/>
                    <f:selectItem itemLabel="Option1" itemValue="Option1"/>
                    <f:selectItem itemLabel="Option2" itemValue="Option2"/>
                    <f:selectItem itemLabel="Option3" itemValue="Option3"/>
                    <f:facet name="footer">
                        <p:divider styleClass="mt-0" />
                        <h:outputText value="3 options" style="font-weight:bold;"/>
                    </f:facet>
                </p:selectOneMenu>
            </div>
            <div class="field col-12 md:col-4">
                <p:outputLabel for="@next" value="Grouping"/>
                <p:selectOneMenu id="group" value="#{selectOneMenuView.countryGroup}">
                    <f:selectItem itemLabel="Select One" itemValue=""/>
                    <f:selectItems value="#{selectOneMenuView.countriesGroup}"/>
                </p:selectOneMenu>
            </div>
            <div class="field col-12 md:col-4">
                <p:outputLabel for="@next" value="Editable"/>
                <p:selectOneMenu id="city" value="#{selectOneMenuView.city}" editable="true">
                    <f:selectItem itemLabel="Select One" itemValue=""/>
                    <f:selectItems value="#{selectOneMenuView.cities}"/>
                </p:selectOneMenu>
            </div>
            <div class="field col-12 md:col-4">
                <p:outputLabel value="Label"/>
                <p:selectOneMenu id="labeled" value="#{selectOneMenuView.labeled}" label="Always Display Label"
                                alwaysDisplayLabel="true">
                    <f:selectItems value="#{selectOneMenuView.cities}"/>
                </p:selectOneMenu>
            </div>
            <div class="field col-12 md:col-4">
                <p:outputLabel for="@next" value="Advanced"/>
                <p:selectOneMenu id="advanced" value="#{selectOneMenuView.country}" converter="#{countryConverter}"
                                panelStyle="width:180px" var="c"
                                filter="true" filterMatchMode="startsWith" filterNormalize="true">
                    <f:selectItems value="#{selectOneMenuView.countries}" var="country"
                                itemLabel="#{country.name}" itemValue="#{country}"/>
                    <p:column style="width:10%">
                        <span class="flag flag-#{c.code}" style="width: 30px; height: 20px"/>
                    </p:column>
                    <p:column>
                        <f:facet name="header">
                            <h:outputText value="Name"/>
                        </f:facet>
                        <h:outputText value="#{c.name}"/>
                    </p:column>
                    <f:facet name="footer">
                        <h:outputText value="#{selectOneMenuView.countries.size()} countries"
                                    style="font-weight:bold;" styleClass="py-1 block"/>
                    </f:facet>
                </p:selectOneMenu>
            </div>
            <div class="field col-12 md:col-4">
                <p:outputLabel for="@next" value="Lazy"/>
                <p:selectOneMenu id="lazy" value="#{selectOneMenuView.option}" dynamic="true">
                    <f:selectItem itemLabel="Select One" itemValue=""/>
                    <f:selectItems value="#{selectOneMenuView.options}"/>
                </p:selectOneMenu>
            </div>
            <div class="field col-12 md:col-4">
                <p:outputLabel for="@next" value="Hide NoSelection Option"/>
                <p:selectOneMenu id="hideNoselectionOption" value="#{selectOneMenuView.hideNoSelectOption}"
                                hideNoSelectionOption="#{not empty selectOneMenuView.hideNoSelectOption}">
                    <p:ajax update="@this" process="@this"/>
                    <f:selectItem itemLabel="Select One" itemValue="#{null}" noSelectionOption="true"/>
                    <f:selectItem itemLabel="Option1" itemValue="Option1"/>
                    <f:selectItem itemLabel="Option2" itemValue="Option2"/>
                    <f:selectItem itemLabel="Option3" itemValue="Option3"/>
                </p:selectOneMenu>
            </div>
            <div class="field col-12 md:col-4">
                <p:outputLabel for="@next" value="Long Item Label"/>
                <p:selectOneMenu id="longItemLabel" value="#{selectOneMenuView.longItemLabel}">
                    <f:selectItem itemLabel="Zero" itemValue="0"/>
                    <f:selectItem itemLabel="One" itemValue="1"/>
                    <f:selectItem itemLabel="Two" itemValue="2"/>
                    <f:selectItem itemLabel="Three" itemValue="3"/>
                    <f:selectItem itemLabel="Four" itemValue="4"/>
                    <f:selectItem itemLabel="Five" itemValue="5"/>
                    <f:selectItem itemLabel="Six" itemValue="6"/>
                    <f:selectItem itemLabel="Seven" itemValue="7"/>
                    <f:selectItem itemLabel="Long item here not necessary in the end" itemValue="99"/>
                    <f:selectItem itemLabel="Eight" itemValue="8"/>
                    <f:selectItem itemLabel="Nine" itemValue="9"/>
                    <f:selectItem itemLabel="Ten and not more than ten " itemValue="10"/>
                </p:selectOneMenu>
            </div>
            <div class="field col-12 md:col-4">
                <p:outputLabel for="@next" value="RTL"/>
                <p:selectOneMenu id="trl" value="#{selectOneMenuView.rtl}" dir="rtl">
                    <f:selectItem itemLabel="Select One" itemValue=""/>
                    <f:selectItem itemLabel="Option1" itemValue="Option1"/>
                    <f:selectItem itemLabel="Option2" itemValue="Option2"/>
                    <f:selectItem itemLabel="Option3" itemValue="Option3"/>
                </p:selectOneMenu>
            </div>
            <div class="field col-12 md:col-4">
                <p:outputLabel for="selectOneMenuIcon" value="Icons" />
                <h:panelGroup styleClass="ui-inputgroup">
                    <h:panelGroup id="icon" styleClass="ui-inputgroup-addon">
                        <i class="pi pi-#{selectOneMenuView.icon}"/>
                    </h:panelGroup>
                    <p:selectOneMenu id="selectOneMenuIcon" value="#{selectOneMenuView.icon}" var="item">
                        <f:selectItems value="#{['flag','wallet','map','link']}" var="item" itemLabel="#{item}"
                            itemValue="#{item}" />
                        <p:column><i class="pi pi-#{item}" /> #{item} </p:column>
                        <p:ajax update="@parent:@parent:icon" />
                    </p:selectOneMenu>
                </h:panelGroup>
            </div>
        </div>
    </h:form>
</div>
package org.primefaces.showcase.view.input;
import org.primefaces.showcase.domain.Country;
import org.primefaces.showcase.service.CountryService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.RequestScoped;
import jakarta.faces.model.SelectItem;
import jakarta.faces.model.SelectItemGroup;
import jakarta.inject.Inject;
import jakarta.inject.Named;
@Named
@RequestScoped
public class SelectOneMenuView {
    private String selectedOption;
    private String rtl;
    private String hideNoSelectOption;
    private String countryGroup;
    private List<SelectItem> countriesGroup;
    private String city;
    private Map<String, String> cities = new HashMap<>();
    private Country country;
    private List<Country> countries;
    private String option;
    private List<String> options;
    private String longItemLabel;
    private String labeled;
    private String icon = "flag";
    @Inject
    private CountryService service;
    @PostConstruct
    public void init() {
        countriesGroup = new ArrayList<>();
        SelectItemGroup europeCountries = new SelectItemGroup("Europe Countries");
        europeCountries.setSelectItems(new SelectItem[]{
            new SelectItem("Germany", "Germany"),
            new SelectItem("Greece", "Greece"),
            new SelectItem("Turkey", "Turkey"),
            new SelectItem("Slovakia", "Slovakia"),
            new SelectItem("Slovenia", "Slovenia"),
            new SelectItem("Spain", "Spain")
        });
        SelectItemGroup americaCountries = new SelectItemGroup("America Countries");
        americaCountries.setSelectItems(new SelectItem[]{
            new SelectItem("United States", "United States"),
            new SelectItem("Brazil", "Brazil"),
            new SelectItem("Mexico", "Mexico")
        });
        countriesGroup.add(europeCountries);
        countriesGroup.add(americaCountries);
        //cities
        cities = new HashMap<>();
        cities.put("New York", "New York");
        cities.put("London", "London");
        cities.put("Paris", "Paris");
        cities.put("Barcelona", "Barcelona");
        cities.put("Istanbul", "Istanbul");
        cities.put("Berlin", "Berlin");
        //countries
        countries = service.getCountries();
        //options
        options = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            options.add("Option " + i);
        }
    }
    public String getSelectedOption() {
        return selectedOption;
    }
    public void setSelectedOption(String selectedOption) {
        this.selectedOption = selectedOption;
    }
    public String getRtl() {
        return rtl;
    }
    public String getHideNoSelectOption() {
        return hideNoSelectOption;
    }
    public void setHideNoSelectOption(String hideNoSelectOption) {
        this.hideNoSelectOption = hideNoSelectOption;
    }
    public void setRtl(String rtl) {
        this.rtl = rtl;
    }
    public String getCountryGroup() {
        return countryGroup;
    }
    public void setCountryGroup(String countryGroup) {
        this.countryGroup = countryGroup;
    }
    public List<SelectItem> getCountriesGroup() {
        return countriesGroup;
    }
    public void setCountriesGroup(List<SelectItem> countriesGroup) {
        this.countriesGroup = countriesGroup;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public Map<String, String> getCities() {
        return cities;
    }
    public void setCities(Map<String, String> cities) {
        this.cities = cities;
    }
    public Country getCountry() {
        return country;
    }
    public void setCountry(Country country) {
        this.country = country;
    }
    public List<Country> getCountries() {
        return countries;
    }
    public String getOption() {
        return option;
    }
    public void setOption(String option) {
        this.option = option;
    }
    public List<String> getOptions() {
        return options;
    }
    public void setOptions(List<String> options) {
        this.options = options;
    }
    public String getLongItemLabel() {
        return longItemLabel;
    }
    public void setLongItemLabel(String longItemLabel) {
        this.longItemLabel = longItemLabel;
    }
    public String getLabeled() {
        return labeled;
    }
    public void setLabeled(String labeled) {
        this.labeled = labeled;
    }
    public String getIcon() {
        return icon;
    }
    public void setIcon(String icon) {
        this.icon = icon;
    }
    public void setService(CountryService service) {
        this.service = service;
    }
}
package org.primefaces.showcase.domain;
import java.io.Serializable;
import java.util.Locale;
import java.util.Objects;
public class Country implements Serializable, Comparable<Country> {
    private int id;
    private String name;
    private String code;
    private Locale locale;
    private boolean rtl;
    public Country() {
    }
    public Country(int id, Locale locale) {
        this(id, locale.getDisplayCountry(), locale.getCountry().toLowerCase(), locale);
    }
    public Country(int id, Locale locale, boolean rtl) {
        this(id, locale.getDisplayCountry(), locale.getCountry().toLowerCase(), locale);
        this.rtl = rtl;
    }
    public Country(int id, String name, String code) {
        this(id, name, code, null);
    }
    public Country(int id, String name, String code, Locale locale) {
        this.id = id;
        this.name = name;
        this.code = code;
        this.locale = locale;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public Locale getLocale() {
        return locale;
    }
    public void setLocale(Locale locale) {
        this.locale = locale;
    }
    public String getLanguage() {
        return locale == null ? "en" : locale.getLanguage();
    }
    public String getDisplayLanguage() {
        return locale == null ? "English" : locale.getDisplayLanguage();
    }
    public boolean isRtl() {
        return rtl;
    }
    public void setRtl(boolean rtl) {
        this.rtl = rtl;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Country country = (Country) o;
        return id == country.id
                && Objects.equals(name, country.name)
                && Objects.equals(code, country.code);
    }
    @Override
    public int hashCode() {
        return Objects.hash(id, name, code);
    }
    @Override
    public String toString() {
        return name;
    }
    @Override
    public int compareTo(Country o) {
        return name.compareTo(o.name);
    }
}
package org.primefaces.showcase.service;
import org.primefaces.showcase.domain.Country;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Named;
@Named
@ApplicationScoped
public class CountryService {
    private List<Country> countries;
    private Map<Integer, Country> countriesAsMap;
    private List<Country> locales;
    private Map<Integer, Country> localesAsMap;
    public static Stream<Country> toCountryStream(String... isoCodes) {
        return Stream.of(isoCodes)
                .map(isoCode -> new Locale("", isoCode))
                .map(CountryService::toCountry);
    }
    public static Country toCountry(Locale locale) {
        return CountryService.toCountry(locale, false);
    }
    public static Country toCountry(Locale locale, boolean rtl) {
        //use hash code from locale to have a reproducible ID (required for CountryConverter)
        return new Country(locale.hashCode(), locale, rtl);
    }
    @PostConstruct
    public void init() {
        countries = CountryService.toCountryStream(Locale.getISOCountries())
                .sorted(Comparator.comparing(Country::getName))
                .collect(Collectors.toList());
        locales = new ArrayList<>();
        locales.add(CountryService.toCountry(Locale.US));
        locales.add(CountryService.toCountry(Locale.UK));
        locales.add(CountryService.toCountry(new Locale("en", "AU")));
        locales.add(CountryService.toCountry(Locale.FRANCE));
        locales.add(CountryService.toCountry(Locale.GERMANY));
        locales.add(CountryService.toCountry(new Locale("de", "AT")));
        locales.add(CountryService.toCountry(new Locale("de", "CH")));
        locales.add(CountryService.toCountry(Locale.ITALY));
        locales.add(CountryService.toCountry(Locale.KOREA));
        locales.add(CountryService.toCountry(new Locale("es", "ES")));
        locales.add(CountryService.toCountry(new Locale("ca", "ES")));
        locales.add(CountryService.toCountry(new Locale("nl", "NL")));
        locales.add(CountryService.toCountry(new Locale("pt", "BR")));
        locales.add(CountryService.toCountry(new Locale("pt", "PT")));
        locales.add(CountryService.toCountry(new Locale("ar", "SA"), true));
        locales.add(CountryService.toCountry(new Locale("ar", "TN"), true));
        locales.add(CountryService.toCountry(new Locale("bg", "BG")));
        locales.add(CountryService.toCountry(new Locale("bn", "BD")));
        locales.add(CountryService.toCountry(new Locale("bs", "BA")));
        locales.add(CountryService.toCountry(new Locale("cs", "CZ")));
        locales.add(CountryService.toCountry(new Locale("el", "GR")));
        locales.add(CountryService.toCountry(new Locale("fa", "IR"), true));
        locales.add(CountryService.toCountry(new Locale("fi", "FI")));
        locales.add(CountryService.toCountry(new Locale("da", "DK")));
        locales.add(CountryService.toCountry(new Locale("hi", "IN")));
        locales.add(CountryService.toCountry(new Locale("in", "ID")));
        locales.add(CountryService.toCountry(new Locale("hr", "HR")));
        locales.add(CountryService.toCountry(new Locale("ja", "JP")));
        locales.add(CountryService.toCountry(new Locale("hu", "HU")));
        locales.add(CountryService.toCountry(new Locale("he", "IL"), true));
        locales.add(CountryService.toCountry(new Locale("ka", "GE")));
        locales.add(CountryService.toCountry(new Locale("ckb", "IQ"), true));
        locales.add(CountryService.toCountry(new Locale("km", "KH")));
        locales.add(CountryService.toCountry(new Locale("ky", "KG")));
        locales.add(CountryService.toCountry(new Locale("kk", "KZ")));
        locales.add(CountryService.toCountry(new Locale("lt", "LT")));
        locales.add(CountryService.toCountry(new Locale("lv", "LV")));
        locales.add(CountryService.toCountry(new Locale("ms", "MY")));
        locales.add(CountryService.toCountry(new Locale("no", "NO")));
        locales.add(CountryService.toCountry(new Locale("pl", "PL")));
        locales.add(CountryService.toCountry(new Locale("ro", "RO")));
        locales.add(CountryService.toCountry(new Locale("ru", "RU")));
        locales.add(CountryService.toCountry(new Locale("sk", "SK")));
        locales.add(CountryService.toCountry(new Locale("sl", "SI")));
        locales.add(CountryService.toCountry(new Locale("sr", "BA")));
        locales.add(CountryService.toCountry(new Locale("sr", "RS")));
        locales.add(CountryService.toCountry(new Locale("sv", "SE")));
        locales.add(CountryService.toCountry(new Locale("th", "TH")));
        locales.add(CountryService.toCountry(new Locale("tr", "TR")));
        locales.add(CountryService.toCountry(new Locale("uk", "UA")));
        locales.add(CountryService.toCountry(new Locale("uz", "UZ")));
        locales.add(CountryService.toCountry(new Locale("vi", "VN")));
        locales.add(CountryService.toCountry(Locale.SIMPLIFIED_CHINESE));
        locales.add(CountryService.toCountry(Locale.TRADITIONAL_CHINESE));
    }
    public List<Country> getCountries() {
        return new ArrayList<>(countries);
    }
    public Map<Integer, Country> getCountriesAsMap() {
        if (countriesAsMap == null) {
            countriesAsMap = getCountries().stream().collect(Collectors.toMap(Country::getId, country -> country));
        }
        return countriesAsMap;
    }
    public List<Country> getLocales() {
        return new ArrayList<>(locales);
    }
    public Map<Integer, Country> getLocalesAsMap() {
        if (localesAsMap == null) {
            localesAsMap = getLocales().stream().collect(Collectors.toMap(Country::getId, country -> country));
        }
        return localesAsMap;
    }
}
package org.primefaces.showcase.convert;
import org.primefaces.showcase.domain.Country;
import org.primefaces.showcase.service.CountryService;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.component.UIComponent;
import jakarta.faces.context.FacesContext;
import jakarta.faces.convert.Converter;
import jakarta.faces.convert.ConverterException;
import jakarta.faces.convert.FacesConverter;
import jakarta.inject.Inject;
import jakarta.inject.Named;
@Named
@ApplicationScoped
@FacesConverter(value = "countryConverter", managed = true)
public class CountryConverter implements Converter<Country> {
    @Inject
    private CountryService countryService;
    @Override
    public Country getAsObject(FacesContext context, UIComponent component, String value) {
        if (value != null && !value.trim().isEmpty()) {
            try {
                return countryService.getCountriesAsMap().get(Integer.parseInt(value));
            }
            catch (NumberFormatException e) {
                throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid country."));
            }
        }
        else {
            return null;
        }
    }
    @Override
    public String getAsString(FacesContext context, UIComponent component, Country value) {
        if (value != null) {
            return String.valueOf(value.getId());
        }
        else {
            return null;
        }
    }
}