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

org.omnifaces.component.input.ViewParam Maven / Gradle / Ivy

There is a newer version: 5.0-M2
Show newest version
/*
 * Copyright 2012 OmniFaces.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.omnifaces.component.input;

import static org.omnifaces.util.Faces.getELContext;
import static org.omnifaces.util.Faces.isPostback;

import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UIViewParameter;
import javax.faces.context.FacesContext;
import javax.faces.convert.ConverterException;
import javax.faces.event.PostValidateEvent;
import javax.faces.event.PreValidateEvent;

import org.omnifaces.util.MapWrapper;

/**
 * 

* The <o:viewParam> is a component that extends the standard <f:viewParam> and * provides a stateless mode of operation and fixes the issue wherein null model values are converted to empty string * parameters in query string (e.g. when includeViewParams=true) and the (bean) validation never being * triggered when the parameter is completely absent in query string, causing e.g. @NotNull to fail. * *

Stateless mode to avoid unnecessary conversion, validation and model updating on postbacks

*

* The standard {@link UIViewParameter} implementation calls the model setter again after postback. This is not always * desired when being bound to a view scoped bean and can lead to performance problems when combined with an expensive * converter. To solve this, this component by default stores the submitted value as a component property instead of in * the model (and thus in the view state in case the binding is to a view scoped bean). *

* The standard {@link UIViewParameter} implementation calls the converter and validators again on postbacks. This is * not always desired when you have e.g. a required="true", but the parameter is not retained on form * submit. You would need to retain it on every single command link/button by <f:param>. To solve * this, this component doesn't call the converter and validators again on postbacks. * *

Using name as default for label

*

* The <o:viewParam> also provides a default for the label atrribute. When the * label attribute is omitted, the name attribute will be used as label. * *

Avoid unnecessary empty parameter in query string

*

* The standard {@link UIViewParameter} implementation calls the converter regardless of whether the evaluated model * value is null or not. As converters by specification return an empty string in case of null * value, this is being added to the query string as an empty parameter when e.g. includeViewParams=true is * used. This is not desired. The workaround was added in OmniFaces 1.8. * *

Support bean validation and triggering validate events on null value

*

* The standard {@link UIViewParameter} implementation uses in JSF 2.0-2.2 an internal "is required" check when the * submitted value is null, hereby completely bypassing the standard {@link UIInput} validation, including * any bean validation annotations and even the {@link PreValidateEvent} and {@link PostValidateEvent} events. This is * not desired. The workaround was added in OmniFaces 2.0. In JSF 2.3, this has been fixed and has only effect when * javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL context param is set to true. * *

Default value when no parameter is set

*

* The <o:viewParam> also supports providing a default value via the new default * attribute. When the parameter is not available, then the value specified in default attribute will be * set in the model instead. The support was added in OmniFaces 2.2. * *

Usage

*

* You can use it the same way as <f:viewParam>, you only need to change f: to * o:. *

 * <o:viewParam name="foo" value="#{bean.foo}" />
 * 
* * @author Arjan Tijms * @author Bauke Scholtz */ @FacesComponent(ViewParam.COMPONENT_TYPE) public class ViewParam extends UIViewParameter { // Public constants ----------------------------------------------------------------------------------------------- public static final String COMPONENT_TYPE = "org.omnifaces.component.input.ViewParam"; // Variables ------------------------------------------------------------------------------------------------------ private String submittedValue; private Map attributeInterceptMap; // Actions -------------------------------------------------------------------------------------------------------- @Override public void processDecodes(FacesContext context) { // Ignore any request parameters that are present when the postback is done. if (!context.isPostback()) { super.processDecodes(context); } } @Override public void processValidators(FacesContext context) { if (!context.isPostback()) { if (isEmpty(getSubmittedValue())) { setSubmittedValue(getDefault()); } if (getSubmittedValue() == null) { setSubmittedValue(""); // Workaround for it never triggering the (bean) validation when unspecified. } super.processValidators(context); } } @Override public Map getAttributes() { if (attributeInterceptMap == null) { attributeInterceptMap = new MapWrapper(super.getAttributes()) { private static final long serialVersionUID = -7674000948288609007L; @Override public Object get(Object key) { if ("label".equals(key)) { return getLabel(); } else { return super.get(key); } } private Object getLabel() { // First check if our wrapped Map has the label Object label = super.get("label"); if (label == null || (label instanceof String && ((String) label).isEmpty())) { // Next check if our outer component has a value expression for the label ValueExpression labelExpression = ViewParam.this.getValueExpression("label"); if (labelExpression != null) { label = labelExpression.getValue(getELContext()); } } // No explicit label defined, default to "name" (which is in many cases the most sane label anyway). if (label == null) { label = ViewParam.this.getName(); } return label; } }; } return attributeInterceptMap; } /** * When there's a value expression and the evaluated model value is null, then just return * null instead of delegating to default implementation which would return an empty string when a * converter is attached. * @since 1.8 */ @Override public String getStringValueFromModel(FacesContext context) throws ConverterException { ValueExpression ve = getValueExpression("value"); Object value = (ve != null) ? ve.getValue(context.getELContext()) : null; return (value != null) ? super.getStringValueFromModel(context) : null; } // Attribute getters/setters -------------------------------------------------------------------------------------- @Override public String getSubmittedValue() { return submittedValue; } @Override public void setSubmittedValue(Object submittedValue) { this.submittedValue = (String) submittedValue; // Don't delegate to statehelper to keep it stateless. } /** * Returns the default value in case the actual request parameter is null or empty. * @return The default value in case the actual request parameter is null or empty. * @since 2.2 */ public String getDefault() { return (String) getStateHelper().eval("default"); } /** * Sets the default value in case the actual request parameter is null or empty. * @param defaultValue The default value in case the actual request parameter is null or empty. * @since 2.2 */ public void setDefault(String defaultValue) { getStateHelper().put("default", defaultValue); } @Override public boolean isRequired() { // The request parameter is ignored on postbacks, however it's already present in the view scoped bean. // So we can safely skip the required validation on postbacks. return !isPostback() && super.isRequired(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy