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

org.omnifaces.taghandler.TagAttribute Maven / Gradle / Ivy

/*
 * Copyright 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
 *
 *     https://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.taghandler;

import static org.omnifaces.util.Components.createValueExpression;

import java.io.IOException;

import jakarta.el.ValueExpression;
import jakarta.el.VariableMapper;
import jakarta.faces.component.UIComponent;
import jakarta.faces.view.facelets.FaceletContext;
import jakarta.faces.view.facelets.TagConfig;
import jakarta.faces.view.facelets.TagHandler;

import org.omnifaces.el.DelegatingVariableMapper;

/**
 * 

* The <o:tagAttribute> is a tag handler that can be used to explicitly declare a tag attribute on * a Facelets tag file. This makes sure that any tag attribute with the same name on a parent tag file is cleared out, * which does not properly happen in Mojarra. *

* Consider the following custom tag structure: *

 * <my:tag id="foo">
 *     <my:tag id="bar" />
 * </my:tag>
 * 
*

* Inside the nested tag, the #{id} will just evaluate to "bar". However, if this isn't * declared on the nested tag like so, *

 * <my:tag id="foo">
 *     <my:tag />
 * </my:tag>
 * 
*

* then #{id} of the nested tag would evaluate to "foo" instead of null, even when you explicitly * specify the attribute in the *.taglib.xml file. *

* This tag handler is designed to overcome this peculiar problem and unintuitive behavior of nested tagfiles in * Mojarra. * *

Usage

*

* Just declare the attribute name in top of the tagfile as below. *

 * <o:tagAttribute name="id" />
 * 
*

* You can optionally provide a default value. *

 * <o:tagAttribute name="type" default="text" />
 * 
* Since OmniFaces 2.7/3.2 there is a special case for a <o:tagAttribute name="id"> without * a default value: it will override any autogenerated ID into the form of j_ido[tagId] where [tagId] * is the <o:tagAttribute> tag's own unique ID. * * @author Arjan Tijms. * @since 2.1 */ public class TagAttribute extends TagHandler { private final String name; private final jakarta.faces.view.facelets.TagAttribute defaultValue; /** * The tag constructor. * @param config The tag config. */ public TagAttribute(TagConfig config) { super(config); name = getRequiredAttribute("name").getValue(); defaultValue = getAttribute("default"); } @Override public void apply(FaceletContext context, UIComponent parent) throws IOException { DelegatingVariableMapper variableMapper = getDelegatingVariableMapper(context); ValueExpression valueExpression = variableMapper.resolveWrappedVariable(name); if (valueExpression == null) { if (defaultValue != null) { valueExpression = defaultValue.getValueExpression(context, Object.class); } else if ("id".equals(name)) { valueExpression = createValueExpression("#{'j_ido" + context.generateUniqueId(this.tagId) + "'}", String.class); variableMapper.setWrappedVariable(name, valueExpression); return; } } variableMapper.setVariable(name, valueExpression); } private DelegatingVariableMapper getDelegatingVariableMapper(FaceletContext context) { VariableMapper variableMapper = context.getVariableMapper(); if (variableMapper instanceof DelegatingVariableMapper) { return (DelegatingVariableMapper) variableMapper; } DelegatingVariableMapper delegatingVariableMapper = new DelegatingVariableMapper(variableMapper); context.setVariableMapper(delegatingVariableMapper); return delegatingVariableMapper; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy