All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jakarta.faces.component.UISelectOne Maven / Gradle / Ivy

Go to download

Jakarta Faces defines an MVC framework for building user interfaces for web applications, including UI components, state management, event handing, input validation, page navigation, and support for internationalization and accessibility.

There is a newer version: 4.1.2
Show newest version
/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package jakarta.faces.component;

import jakarta.faces.application.FacesMessage;
import jakarta.faces.component.visit.VisitContext;
import jakarta.faces.component.visit.VisitResult;
import jakarta.faces.context.FacesContext;

/**
 * 

* UISelectOne is a {@link UIComponent} that represents the user's choice * of zero or one items from among a discrete set of available options. The user can modify the selected value. * Optionally, the component can be preconfigured with a currently selected item, by storing it as the * value property of the component. *

* *

* This component is generally rendered as a select box or a group of radio buttons. *

* *

* By default, the rendererType property is set to "jakarta.faces.Menu". This value can be * changed by calling the setRendererType() method. *

*/ public class UISelectOne extends UIInput { // ------------------------------------------------------ Manifest Constants /** *

* The standard component type for this component. *

*/ public static final String COMPONENT_TYPE = "jakarta.faces.SelectOne"; /** *

* The standard component family for this component. *

*/ public static final String COMPONENT_FAMILY = "jakarta.faces.SelectOne"; /** *

* The message identifier of the {@link jakarta.faces.application.FacesMessage} to be created if a value not matching * the available options is specified. */ public static final String INVALID_MESSAGE_ID = "jakarta.faces.component.UISelectOne.INVALID"; enum PropertyKeys { /** *

* Specifies the name of the radio button group. * * @since 2.3 */ group } // ------------------------------------------------------------ Constructors /** *

* Create a new {@link UISelectOne} instance with default property values. *

*/ public UISelectOne() { super(); setRendererType("jakarta.faces.Menu"); } // -------------------------------------------------------------- Properties @Override public String getFamily() { return COMPONENT_FAMILY; } /** *

* Returns the name of the radio button group. *

* Radio button components having the same group within a UIForm parent will uncheck all others when being * checked. If the value attribute is absent then the one from first component of the group will be used. * If the UISelectItem child is absent then the one from first component of the group will be used. * * @return The name of the radio button group. * @since 2.3 */ public String getGroup() { return (String) getStateHelper().eval(PropertyKeys.group); } /** *

* Sets the name of the radio button group. * * @param group The name of the radio button group. * @since 2.3 */ public void setGroup(String group) { getStateHelper().put(PropertyKeys.group, group); } // ------------------------------------------------------ Validation Methods /** *

* If {@link #getGroup()} is set, and {@link #getSubmittedValue()} is empty, and at least one other component having the * same group within a UIForm parent has a non-empty {@link #getSubmittedValue()} or returns * true on {@link #isLocalValueSet()} or returns false on {@link #isValid()}, then skip * validation for current component, else perform standard superclass processing by * super.processValidators(context). *

*/ @Override public void processValidators(FacesContext context) { final String group = getGroup(); if (group != null && isEmpty(getSubmittedValue())) { final String clientId = getClientId(context); final UIComponent groupContainer = getGroupContainer(context, this); final boolean[] alreadySubmittedOrValidatedAsGroup = new boolean[1]; groupContainer.visitTree(VisitContext.createVisitContext(context), (visitContext, target) -> { if (target instanceof UISelectOne) { UISelectOne radio = (UISelectOne) target; if (isOtherMemberOfSameGroup(context, group, clientId, radio) && isAlreadySubmittedOrValidated(radio)) { alreadySubmittedOrValidatedAsGroup[0] = true; return VisitResult.COMPLETE; } } return VisitResult.ACCEPT; }); if (alreadySubmittedOrValidatedAsGroup[0]) { return; } } super.processValidators(context); } private static UIComponent getGroupContainer(FacesContext context, UISelectOne radio) { UIComponent namingContainer = radio.getNamingContainer(); while (namingContainer != null && !(namingContainer instanceof UIForm) && namingContainer.getParent() != null) { namingContainer = namingContainer.getParent().getNamingContainer(); } return namingContainer != null ? namingContainer : context.getViewRoot(); } private static boolean isOtherMemberOfSameGroup(FacesContext context, String group, String clientId, UISelectOne radio) { return group.equals(radio.getGroup()) && !clientId.equals(radio.getClientId(context)); } private static boolean isAlreadySubmittedOrValidated(EditableValueHolder input) { return !isEmpty(input.getSubmittedValue()) || input.isLocalValueSet() || !input.isValid(); } /** *

* In addition to the standard validation behavior inherited from * {@link UIInput}, ensure that any specified value is equal to one of the available options. Before comparing each * option, coerce the option value type to the type of this component's value following the Expression Language coercion * rules. If the specified value is not equal to any of the options, enqueue an error message and set the * valid property to false. *

* *

* If {@link #isRequired} returns true, and the current value is equal to the value of an inner * {@link UISelectItem} whose {@link UISelectItem#isNoSelectionOption} method returns true, enqueue an * error message and set the valid property to false. *

* * @param context The {@link FacesContext} for the current request * * @param value The converted value to test for membership. * * @throws NullPointerException if context is null */ @Override protected void validateValue(FacesContext context, Object value) { super.validateValue(context, value); // Skip validation if it is not necessary if (!isValid() || value == null) { return; } // Ensure that the value matches one of the available options boolean found = SelectUtils.matchValue(getFacesContext(), this, value, new SelectItemsIterator(context, this), getConverter()); boolean isNoSelection = SelectUtils.valueIsNoSelectionOption(getFacesContext(), this, value, new SelectItemsIterator(context, this), getConverter()); // Enqueue an error message if an invalid value was specified if (!found || isRequired() && isNoSelection) { FacesMessage message = MessageFactory.getMessage(context, INVALID_MESSAGE_ID, MessageFactory.getLabel(context, this)); context.addMessage(getClientId(context), message); setValid(false); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy