f:ajax 上的 onevent 导致模型未更新

发布于 2025-01-05 22:52:20 字数 2404 浏览 1 评论 0原文

我在网站上添加了 TinyMCE(JSF-2、Tomcat 7、Mojarra 2.1.6)。当用户单击“刷新”按钮时,编辑器内的 html 文本将被解析并打印到页面上的其他位置。

我必须在 Ajax 请求之前关闭 TinyMCE(否则我最终会得到两个编辑器)。 TinyMCE 文档中也建议这样做。

因此,我向按钮添加了一个 f:ajax 事件:

<h:commandButton value="#{msg['rt.refresh']}" action="#{updateTextAction.execute}" onclick="cleanupRte();">
<f:ajax event="action" execute="@this" render="@all" onevent="disposeTinyMce" />
</h:commandButton>

正确调用了 javascript 函数:

function cleanupRte() {
  tinyMCE.triggerSave();

  return true;
}

以及 onevent 方法:

function disposeTinyMce(e) {

    if(e.status == 'begin') {
        tinyMCE.triggerSave();

        var elem = document.getElementById("mainForm:rteExtAdr:input");
        alert(elem.value);

        tinyMCE.execCommand('mceRemoveControl', false, 'mainForm:rteExtAdr:input');
    }
    if(e.status == 'complete') {
    }
    if(e.status == 'success') { 
        tinyMCE.execCommand('mceAddControl', false, 'mainForm:rteExtAdr:input');
    }

    return true;
}

该方法禁用编辑器并将其添加回页面。这工作正常。

问题是尽管警报显示了正确的值,但模型并未使用文本字段中的值进行更新。该请求还包含文本字段中的“旧”值。

是否有什么东西会阻止 ajax 调用查看当前表单值? 或者它是否在执行 onevent 函数之前读取值?

如果我完全删除 f:ajax 标签,模型会更新,但我会遇到 TinyMce 编辑器在响应后重复的问题。

init 调用:

tinyMCE.init({
    mode : "textareas",
    theme : "advanced",
    editor_selector : "sesamWysiwyg", 
    language : "de",
    force_br_newlines : true,
    force_p_newlines : false,
    inline_styles : false,
    forced_root_block : '', // Needed for 3.x
    plugins : "autolink,lists,style,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,searchreplace,print,paste,directionality,noneditable,visualchars,nonbreaking,xhtmlxtras,wordcount,advlist",

    formats : {
            underline : {inline : 'u', exact : true},
            strikethrough : {inline : 'del', exact : true}
    },

    theme_advanced_buttons1 : "bold,underline,strikethrough,|,cut,copy,paste,pastetext,pasteword,search,replace,|,undo,redo,|,code,removeformat,|,charmap",
        theme_advanced_buttons2 : "",
        theme_advanced_buttons3 : "",
        theme_advanced_buttons4 : "",
        theme_advanced_toolbar_location : "top",
        theme_advanced_toolbar_align : "left",

        content_css : "css/content.css",

    });

任何想法或建议都会很棒!

谢谢 :)

I've added TinyMCE on a website (JSF-2, Tomcat 7, Mojarra 2.1.6). When a user clicks on a 'refresh' button the html text inside the editor is parsed and printed somewhere else on the page.

I have to turn off TinyMCE before the Ajax request (otherwise I will end up with two editors). This is also recommended in the TinyMCE documentation.

So I added an f:ajax event to the button:

<h:commandButton value="#{msg['rt.refresh']}" action="#{updateTextAction.execute}" onclick="cleanupRte();">
<f:ajax event="action" execute="@this" render="@all" onevent="disposeTinyMce" />
</h:commandButton>

the javascript functions are called properly:

function cleanupRte() {
  tinyMCE.triggerSave();

  return true;
}

and the onevent method:

function disposeTinyMce(e) {

    if(e.status == 'begin') {
        tinyMCE.triggerSave();

        var elem = document.getElementById("mainForm:rteExtAdr:input");
        alert(elem.value);

        tinyMCE.execCommand('mceRemoveControl', false, 'mainForm:rteExtAdr:input');
    }
    if(e.status == 'complete') {
    }
    if(e.status == 'success') { 
        tinyMCE.execCommand('mceAddControl', false, 'mainForm:rteExtAdr:input');
    }

    return true;
}

which disables the editor and adds it back to the page. This is working fine.

The problem is the model is not updated with the value from the textfield although the alert shows the correct value. The request also contains the 'old' value from the textfield.

Is there something that would prevent the ajax call to see the current form values?
or does it read the values before it executes the onevent function?

If I remove the f:ajax tag completely the model is updated but then I have the issues with the TinyMce editor getting duplicated after the response.

the init call:

tinyMCE.init({
    mode : "textareas",
    theme : "advanced",
    editor_selector : "sesamWysiwyg", 
    language : "de",
    force_br_newlines : true,
    force_p_newlines : false,
    inline_styles : false,
    forced_root_block : '', // Needed for 3.x
    plugins : "autolink,lists,style,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,searchreplace,print,paste,directionality,noneditable,visualchars,nonbreaking,xhtmlxtras,wordcount,advlist",

    formats : {
            underline : {inline : 'u', exact : true},
            strikethrough : {inline : 'del', exact : true}
    },

    theme_advanced_buttons1 : "bold,underline,strikethrough,|,cut,copy,paste,pastetext,pasteword,search,replace,|,undo,redo,|,code,removeformat,|,charmap",
        theme_advanced_buttons2 : "",
        theme_advanced_buttons3 : "",
        theme_advanced_buttons4 : "",
        theme_advanced_toolbar_location : "top",
        theme_advanced_toolbar_align : "left",

        content_css : "css/content.css",

    });

Any ideas or suggestions would be great!

thanks :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烟若柳尘 2025-01-12 22:52:20

这不是由 onevent 处理函数引起的。这是由 execute="@this" 属性引起的。 @this 基本上意味着只有当前 组件将被执行/处理。如果您想处理整个表单,包括所有包含的输入元素,则需要使用 execute="@form"

<h:commandButton value="#{msg['rt.refresh']}" action="#{updateTextAction.execute}" onclick="cleanupRte();">
    <f:ajax execute="@form" render="@all" onevent="disposeTinyMce" />
</h:commandButton>

这样,模型将使用所有已处理输入元素的值进行更新。

或者,如果您只想处理某些输入,则需要使用例如 execute="input",其中 input 是输入组件的 ID。它可以采用空格分隔的(相对)客户端 ID 字符串。


至于重新发明轮子,看组件库就知道了。 PrimeFaces 例如有 一个组件。这样就可以

<p:editor value="#{bean.text}" />
<p:commandButton value="Save" action="#{bean.save}" />

轻松使用自定义脚本了。

This is not caused by the onevent handler function. This is caused by the execute="@this" attribute. The @this basically means that only the current component will be executed/processed. If you want to process the entire form, including all the containing input elements, you need to use execute="@form" instead.

<h:commandButton value="#{msg['rt.refresh']}" action="#{updateTextAction.execute}" onclick="cleanupRte();">
    <f:ajax execute="@form" render="@all" onevent="disposeTinyMce" />
</h:commandButton>

This way the model will be updated with the values of all processed input elements.

Or if you want to process certain inputs only, you need to use for example execute="input" where input is the ID of the input component. It can take a space separated string of (relative) client IDs.


As to reinventing the wheel, just look at component libraries. PrimeFaces for example has a <p:editor> component. It's then a matter of only

<p:editor value="#{bean.text}" />
<p:commandButton value="Save" action="#{bean.save}" />

without any hassle with custom scripts.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文