使用来自@ManagedBean 的值执行 JS 函数

Execute JS function with value from @ManagedBean

我有一个后端 restservice 调用,返回一个值,我必须用它执行一个 JS 函数(为简单起见,我在前端使用 "alert"。这必须在 JSF 中实现,我很难过。

而且,这就是问题所在,出于性能原因,我希望在单击时执行后端 rest-call。

这是(除其他外)我尝试过的:

<p:commandLink action="#{viewingSessionBean.prepareViewingSession(document)}" oncomplete="alert('#{viewingSessionBean.name(document)}')">
     <p:graphicImage value="documentViewerPopup.png"/>
</p:commandLink>

这里是豆子(为了使观点更清楚而缩短):

@ManagedBean
@ViewScoped
public class ViewingSessionBean implements Serializable {
     private String name;

     public String prepareViewingSession(Document document) {
          name = restClient.call()
          hashMap.put(document.getBlobId(), name);
          return null;  // don't navigate away...
     }

     public String name(Document document) {
         return hashMap.get(document.getBlobId()); // return null if nothing is cached for the document yet there
     }

}

我想做这样的事情(伪代码...没有h:commandScript...,太旧的JSF,没办法升级)

 <h:commandScript action="alert('#{viewingSessionBean.prepareViewingSession(document)}') />

完成起来有点棘手,但仍然可行。

您必须首先牢记一件事:您在 .xhtml 中编写的 JavaScript 代码以 'static' 方式呈现。但是 'static' 是什么意思?这意味着如果您在 JavaScript 代码中引用一个 bean 变量,然后在您的 bean 中更新这个变量值,您打印的 JavaScript 代码将无法看到您刚刚所做的这些更改。在这种情况下,您必须首先更新 JavaScript 代码(使用 ajax)以获取变量中的更改,然后才执行它。

让我们从您的 bean 开始:

@ManagedBean
@ViewScoped
public class ViewingSessionBean implements Serializable {

     private String variable;

     public String getVariable() {
        return this.variable;
     }

     public void updateVariableValue(Document document) {
          variable = restClient.call();
     }

}

现在,.xhtml代码:

<h:form id="form">
    <p:commandLink id="firstLink"
                   actionListener="#{viewSessionBean.updateVariableValue(document)}" 
                   update=":form:secondLink"
                   oncomplete="$('#form\:secondLink').click()"/>
    <p:commandLink id="secondLink" onclick="alert('#{viewSessionBean.variable}')" style="display: none;"/>
</h:form>

注意几点:

第一:使用了两个命令Link,而不是一个,为什么?因为在第一个 Link 的 oncomplete 调用时,bean 变量已经是最新的,但是您的 html 代码不是。因此,为了获得 bean 变量的更新值,我们执行以下操作:

  • 调用actionListener更新bean上的变量值;
  • 在第二个 Link 上进行 ajax 更新以从 bean 获取更新后的值;
  • 调用 oncomplete 方法并点击第二个 Link(现在更新为正确的值);

第二:要调用第二个 Link 的点击,我们必须转义 jQuery 调用中的两个点。

第三:第二个Link设置了display:none样式,使其在屏幕中不可见。

现在只是一些关于它的想法:JSF 与 JavaScript 一起工作得很好,但有时我们必须像这样使用一些笨拙的技巧来完成 "easy" 任务。我并不是说 JSF 不好,但我认为我们可以有更多 'out-of-box' 的方法来处理这类事情。不过只是我的意见。