javascript - 有没有办法从 UIComponent 对象获取生成的 HTML 作为 String 并在 RENDER 响应阶段正确绑定所有 ajax 侦听器?
问题描述
这是对这个问题的跟进。
环境
Primefaces 8.0.RC3
JSF 2.2.15
Tomcat 8.5.47
背景
我有一个扩展的自定义 JSF 组件UIComponentBase
。
public final class Map extends UIComponentBase implements Widget {
// resolveWidgetVar
// a constructor
// getters/setters
}
有MapRenderer
哪个将渲染该组件。
public final class MapRenderer extends CoreRenderer {
@Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
final Map map = (Map) component;
encodeMarkup(context, map);
encodeScript(context, map);
}
private void encodeMarkup(FacesContext context, Map map) throws IOException {
// renders a div
}
private void encodeScript(FacesContext context, Map map) throws IOException {
// renders a script with PF.cw(widgetName, widgetVar, cfg)
}
}
它将是一个基于传单的地图,其中一个图例被定义为一个SelectManyMenu
组件。图例既是图例又是过滤器。挑战在于很好地将所需的一切传递给 JS 端。为此,我采用了这个答案所示的方法- 我基本上编码了一个以编程方式创建SelectManyMenu
到我的Writer
.
然后,我将它分成两部分(因为应该定义控件(这里是图例)的方式 - 请参见下面的函数):
一个 JS 片段
executeInteractiveLegendScript
(用一行来创建一个 Primefaces 小部件)和HTML 片段
getInteractiveLegendHTML
(菜单的标记)。
function (configuration) {
var interactiveLegend = L.control({position: 'bottomleft'});
interactiveLegend.onAdd = function () {
var container = L.DomUtil.create('div', 'interactive-legend');
container.innerHTML = configuration['getInteractiveLegendHTML']();
return container;
};
interactiveLegend.addTo(map);
configuration['executeInteractiveLegendScript']();
}
configuration
是我在 Java 端编译的对象。在某些时候,通过 JS,我将图例添加到地图中。JS 片段正在正确执行,Primefaces 元素正在正确显示 - 这里没有问题。
问题
问题在于为这个以编程方式创建的组件定义客户端行为。
// while rendering the map
SelectManyMenu selectManyMenu = (SelectManyMenu) context.getApplication()
.createComponent(SelectManyMenu.COMPONENT_TYPE);
// setting children and properies
selectManyMenu.addClientBehavior("change", createAjax(context));
selectManyMenu.encodeAll(context);
创建a的方法ClientBehavior
定义如下
private ClientBehavior createAjax(FacesContext context) {
Application application = context.getApplication();
ExpressionFactory expressionFactory = application.getExpressionFactory();
AjaxBehavior behavior = (AjaxBehavior) application.createBehavior(AjaxBehavior.BEHAVIOR_ID);
MethodExpression methodExpression = expressionFactory.createMethodExpression(context.getELContext(), "#{myexpression}", Void.TYPE, new Class[]{String.class});
AjaxBehaviorListenerImpl listener = new AjaxBehaviorListenerImpl(methodExpression, methodExpression, methodExpression);
behavior.setProcess("@this");
// PROBLEM HERE - this listener never gets invoked
behavior.addAjaxBehaviorListener(listener);
return behavior;
}
我怀疑我注册此客户行为的地方,是否为时已晚并且听众根本没有正确注册?
问题是如何让它工作,我应该在哪里创建一个菜单实例并绑定所有的属性/监听器。
@BalusC在他的回答中提到
(假设您正处于调用应用程序阶段;当处于渲染响应阶段时,需要以不同的方式完成):
这证实了我做错了什么。
解决方案
推荐阅读
- c# - Linq 在 List 的属性上取平均值
- javascript - 仅在父级(元素外部)上的 onclick() 时 RemoveChild
- c - 为什么 GNU dd 在 dup2 中重用文件描述符 0 和 1?
- php - Docker - Symfony 4 - Doctrine - 拒绝用户访问
- azure - 使用graph api禁用office365邮箱
- typescript - tslint - 组内的导入源必须按字母顺序排列
- time-complexity - 如何计算代码片段中大θ的时间复杂度?
- windows-installer - 用于卸载 installshield 设置的 C# 代码
- ios - 隐藏导航控制器搜索栏并以编程方式打开大标题
- java - 在不丢失对象引用的情况下内联调用 setter