JSF中h:commandLink未正确包裹内容,HTML渲染不符预期
问题
我在XHTML中编写了如下代码:
<div class="row mt-3"> <div class="col-4 text-center"> <h:commandLink action="#{pwaService.payment(3)}"> <div class="box-info-activity shadow clickable" style="height: 104px!important;width: 104px!important;"> <a class="fa fa-credit-card fa-2x mt-2"></a> <p class="mt-3">#{pwaService.getPrice(3)} ريال</p> <h:outputText styleClass="mt-1" value="یک ساله"/> <p class="mt-3">خرید</p> </div> <f:ajax/> </h:commandLink> </div> </div>
期望JSF渲染后生成如下HTML:
<div class="row mt-3"> <div class="col-4 text-center"> <a id="j_idt13" href="#" onclick="mojarra.ab(this,event,'action',0,0);return false"> <div class="box-info-activity shadow clickable" style="height: 104px!important;width: 104px!important;"><a id="j_idt13" href="#" onclick="mojarra.ab(this,event,'action',0,0);return false"> </a><a class="fa fa-credit-card fa-2x mt-2"></a> <p class="mt-3"> ۵۰۰۰۰۰۰ ريال </p><span class="mt-1">یک ساله</span> <p class="mt-3">خرید</p> </div> </a> </div> </div>
但实际渲染出的HTML如下:
<div class="row mt-3"> <div class="col-4 text-center"><a id="j_idt13" href="#" onclick="mojarra.ab(this,event,'action',0,0);return false"> </a><div class="box-info-activity shadow clickable" style="height: 104px!important;width: 104px!important;"><a id="j_idt13" href="#" onclick="mojarra.ab(this,event,'action',0,0);return false"> </a><a class="fa fa-credit-card fa-2x mt-2"></a> <p class="mt-3"> ۵۰۰۰۰۰۰ ريال </p><span class="mt-1">یک ساله</span> <p class="mt-3">خرید</p> </div> </div> </div>
XHTML文件头部命名空间:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:a="http://xmlns.jcp.org/jsf/passthrough" >
需求是创建一个可点击的div,内部所有内容都能触发点击事件,但实际生成的a标签提前闭合,未包裹div内容,导致点击区域失效。请问为何会出现这种情况?该如何解决?
原因
- HTML规范限制:HTML标准中,
<a>属于行内元素,不能直接包含块级元素(比如<div>)。浏览器的HTML解析器会自动修正这种不规范嵌套,将<a>提前闭合,导致它无法包裹整个<div>。 - 嵌套
<a>标签违规:代码里<div>内部还嵌套了另一个<a>标签(用于Font Awesome图标),而HTML不允许<a>嵌套<a>,这会进一步触发浏览器的自动修正逻辑,加剧标签结构混乱。
解决方法
方法1:用h:commandButton替代h:commandLink
将h:commandLink换成h:commandButton,通过CSS样式把按钮改成块级元素,模拟可点击div的效果:
<div class="row mt-3"> <div class="col-4 text-center"> <h:commandButton action="#{pwaService.payment(3)}" styleClass="box-info-activity shadow clickable border-0 bg-transparent w-100 h-100 p-0"> <i class="fa fa-credit-card fa-2x mt-2"></i> <p class="mt-3">#{pwaService.getPrice(3)} ريال</p> <h:outputText styleClass="mt-1" value="یک ساله"/> <p class="mt-3">خرید</p> <f:ajax/> </h:commandButton> </div> </div>
- 样式说明:
border-0 bg-transparent去掉按钮默认样式,w-100 h-100 p-0让按钮铺满父容器,完全模拟div布局。 - 将原图标
<a>换成<i>,避免嵌套<a>的问题。
方法2:用Pass-through属性给div绑定AJAX事件
利用JSF的Pass-through命名空间,直接给<div>绑定点击事件,触发JSF的AJAX请求:
<div class="row mt-3"> <div class="col-4 text-center"> <div class="box-info-activity shadow clickable" style="height: 104px!important;width: 104px!important;" a:onclick="mojarra.ab(this,event,'action',0,0,'#{pwaService.payment(3)}');return false"> <i class="fa fa-credit-card fa-2x mt-2"></i> <p class="mt-3">#{pwaService.getPrice(3)} ريال</p> <h:outputText styleClass="mt-1" value="یک ساله"/> <p class="mt-3">خرید</p> </div> </div> </div>
- 通过
a:onclick调用Mojarra的AJAX方法mojarra.ab(),指定action为#{pwaService.payment(3)},实现点击div触发后端方法的效果。 - 同样将图标
<a>换成<i>,符合HTML规范。
方法3:升级JSF版本(可选)
部分新版JSF(如JSF 2.3+)对HTML5支持更好,允许h:commandLink渲染成包含块级元素的结构,但前提是页面声明为HTML5文档(<!DOCTYPE html>),且仍需避免嵌套<a>标签。
内容的提问来源于stack exchange,提问作者Farhood Naqizadeh
相关产品推荐
相关产品推荐

