Wicket 保持面板元素的标记ID唯一

Wicket 保持面板元素的标记ID唯一,wicket,Wicket,我有一个面板,用来显示某个位置的信息。我有一个页面,用于显示涉及两个地点的交货预约信息。“我的传递”页面包含两次位置面板-一次用于起点,一次用于目的地。此示例已简化,因此位置只有一个名称属性 问题: 为这两个位置的名称(和其他属性)设置标记ID并保持其唯一性的最佳方法是什么 示例代码 LocationPanel.java public class LocationPanel extends BasePanel { public LocationPanel(String id, Str

我有一个面板,用来显示某个位置的信息。我有一个页面,用于显示涉及两个地点的交货预约信息。“我的传递”页面包含两次位置面板-一次用于起点,一次用于目的地。此示例已简化,因此位置只有一个名称属性

问题: 为这两个位置的名称(和其他属性)设置标记ID并保持其唯一性的最佳方法是什么


示例代码 LocationPanel.java

public class LocationPanel extends BasePanel {

    public LocationPanel(String id, String locCode) {
        super(id);
        init(locCode);
    }

    private void init(String locCode) {
        LocationInfo locModel = new LocationInfo(locCode + " Location");
        CompoundPropertyModel model = new CompoundPropertyModel(locModel);
        Label name = new Label("name");
        setDefaultModel(model);
        add(name);
    }
}
public class SetDeliveryAppointment extends BaseWebPage{

    public SetDeliveryAppointment(String id) {
        super(id);
        init();
    }

    private void init() {
        Panel origin = new RampLocationInformationPanel("origin", "LAX");
        Panel dest = new RampLocationInformationPanel("dest", "DAL");
        WebMarkupContainer delivery = new WebMarkupContainer("delivery");
        delivery.add(origin);
        delivery.add(dest);
        add(delivery);
    }
}
LocationPanel.html

<html xmlns:wicket="http://wicket.apache.org">
<body>
    <wicket:panel>
        <h3><span wicket:id="name">SAMPLE location</span></h3>
    </wicket:panel>
</body>
</html>
<html xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:extend>
    <wicket:container wicket:id="delivery">
        <div wicket:id="origin"></div>
        <div wicket:id="dest"></div>
    </wicket:container>
</wicket:extend>
</body>
</html>
<html>
<body>
    <div id="origin">
        <!-- The exact id doesn't matter -->
        <!-- as long as 'origin' and 'name' are contained in it -->
        <h3><span id="origin_name">LAX location</span></h3>
    </div>
    <div id="dest">
        <h3><span id="dest_name">DAL location</span></h3>
    </div>
</body>
</html>
SetDeliveryAppointment.html

<html xmlns:wicket="http://wicket.apache.org">
<body>
    <wicket:panel>
        <h3><span wicket:id="name">SAMPLE location</span></h3>
    </wicket:panel>
</body>
</html>
<html xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:extend>
    <wicket:container wicket:id="delivery">
        <div wicket:id="origin"></div>
        <div wicket:id="dest"></div>
    </wicket:container>
</wicket:extend>
</body>
</html>
<html>
<body>
    <div id="origin">
        <!-- The exact id doesn't matter -->
        <!-- as long as 'origin' and 'name' are contained in it -->
        <h3><span id="origin_name">LAX location</span></h3>
    </div>
    <div id="dest">
        <h3><span id="dest_name">DAL location</span></h3>
    </div>
</body>
</html>


目标是: 因此,我希望在生成的HTML中看到如下内容

最终HTML视图源目标

<html xmlns:wicket="http://wicket.apache.org">
<body>
    <wicket:panel>
        <h3><span wicket:id="name">SAMPLE location</span></h3>
    </wicket:panel>
</body>
</html>
<html xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:extend>
    <wicket:container wicket:id="delivery">
        <div wicket:id="origin"></div>
        <div wicket:id="dest"></div>
    </wicket:container>
</wicket:extend>
</body>
</html>
<html>
<body>
    <div id="origin">
        <!-- The exact id doesn't matter -->
        <!-- as long as 'origin' and 'name' are contained in it -->
        <h3><span id="origin_name">LAX location</span></h3>
    </div>
    <div id="dest">
        <h3><span id="dest_name">DAL location</span></h3>
    </div>
</body>
</html>

松弛位置
DAL定位
奖金: 这确实是一个贯穿各领域的问题。理想情况下,我们希望每个Wicket组件都有一个唯一的ID,但我们希望它能够根据我们规定的规则进行预测。完美的解决方案将解决这一问题


免责声明:我是Wicket的新手,所以如果这是一个愚蠢的问题,请对我放松点

你可以简单地调用
setMarkupId(“origin”)
setMarkupId(“目的地”)(我不记得是否必须在面板的每个实例上使用
setOutputMarkupId();
)。请记住,您必须注意页面中ID的唯一性(但Wicket不会生成与“origin”或“destination”冲突的名称)

编辑:再解释一下如何做,我会这样写
LocationPanel.java

public class LocationPanel extends BasePanel {

   public LocationPanel(String id, String locCode) {
    super(id);
    //sets the markupId to the wicket:id passed
    //you'll have to make sure you don't have the same wicket:id in the whole hierarchy
    //of your page though 
    setMarkupId(id);
    setOutputMarkupId(true);
    init(locCode);
   }

   private void init(String locCode) {
    LocationInfo locModel = new LocationInfo(locCode + " Location");
    CompoundPropertyModel model = new CompoundPropertyModel(locModel);
    Label name = new Label("name");
    setDefaultModel(model);
    add(name);
  }
}

使用JS时,不应使用#id(例如,在jQuery中使用相对选择器)或生成javascript片段,在其中传递
component.getMarkupId()


关于selenium还不确定,最好使用wicket测试框架(它非常强大)。

所以这里有一种方法可以实现。如果组件的父组件上的模型是
CompoundPropertyModel
的实例,则该父组件的Id可用于更改子组件的标记Id

public class ComponentMarkupListener implements IComponentOnBeforeRenderListener {
  public void onBeforeRender(Component component) {
    if (component instanceof WebMarkupContainer || component instanceof Label) {
        component.setOutputMarkupId(true);

        if((component.getParent().getDefaultModel()) instanceof CompoundPropertyModel ){
          component.setMarkupId(component.getParent().getId()
              +"_"+ component.getId() + "_ID");
        }else{
          component.setMarkupId(component.getId() + "_ID");
        }
    }
  }
}

在使用HTML
和使用HTML
id
之间,始终需要权衡。在开发Wicket组件时,组件的最终目标应该是可重用性,不是吗?我个人的偏好是坚持使用
,尤其是在相同页面上重用组件时。然后通过JS集成、CSS样式和Selenium测试依赖于它们的层次结构(尽可能不特定)。

代码有什么问题?看起来对我来说是正确的。每个组件都可以通过层次结构进行唯一访问。第一个
name
将具有路径
delivery:origin:name
,第二个将是
delivery:dest:name
。Wicket会自动生成唯一的html标记ID(用于javascript/etc)。@kan因为如果我让Wicket负责命名,我会得到
。我需要一个可靠的方法来为JS和可能的Selenium测试引用这些内容。我不完全确定我是否理解你的意思。你能提供代码示例吗?我会编辑我的问题,让它更清楚我在寻找什么。我已经编辑了我的答案,如果我正确地理解了你想要的,我认为它可以做到这一点。还会有两个元素的DOM
id
为“name”吗?似乎您必须将id参数从构造函数传递到init(..)方法,以便可以使用id参数的concat和组件的wicket id调用标签上的setMarkupId和setOutputMarkupId。如果是这样,然后,您还必须这样做,因为每个其他属性都会导致一些代码爆炸。不,因为传递到
面板的
id
分别对应于父容器中的
wicket:id
,在您的情况下,
origin
dest
,我发现我漏掉了origin(u name)的东西,你可以按照你说的concat的类似模式(或者使用cssClass,如果你的目标是能够选择它
#origin.name
),也许我不熟悉你所指的相对选择器。唯一DOM ID的意义不在于它允许您精确定位对象,而不管对象在页面上的什么位置?然后,如果页面布局发生显著变化,您的CSS和JS将不会中断。更不用说DOM
getElementById
的性能优势了。这里的问题是wicket方法。您制作的每个wicket组件都应该是独立的、自包含的。你可以把它们放在任何你想要的地方,而不发生任何冲突。例如,现在您的页面上有一个
交付
。但是明天您需要在同一页面上构建它们的列表,更改这些
ID
s并不是一件小事,不可能为它们提供固定字符串。wicket会自动为它们中的每一个生成唯一的ID。我不同意,而且我认为,与处理wicket自动生成的DOM ID的脆弱性所需的黑客相比,为适应多次交付而需要进行的任何更改都是微不足道的。@Snekse从wicket的角度来看,只需将
WebMarkupContainer
替换为
RepeatingView
,就可以了(当然,如果您没有使用您所要求的任何hack)。所以,如果我希望每个“名字”都有一个唯一的ID,但我希望它是可预测的——即使只是“名字1”、“名字2”等,当名字标签嵌入面板时,我该怎么做?考虑到看似随机的命名,依靠Wicket的自动命名不是一个选项。在一个页面上有两个面板,并且“名称”ID为“namef”和“name11”是不可接受的