How to make TinyMCE work inside an UpdatePanel?

前端 未结 12 928
别跟我提以往
别跟我提以往 2021-02-07 13:28

I\'m trying to do something that many people seem to have been able to do but which I am unable to implement any solution. The TinyMCE control works pretty well in an asp.net fo

相关标签:
12条回答
  • 2021-02-07 13:39

    This solution no longer works for TinyMCE 4.2.3. Instead of using tinymce.mceRemoveControl() you now need to use tinymce.remove(). Here is a full working example:

    The Page

        <%@ Page Title="" Language="C#" MasterPageFile="~/MasterPages/Frame.master" AutoEventWireup="true" CodeFile="FullImplementation.aspx.cs" 
      Inherits="TinyMCE" ValidateRequest="false" %>
    
    <asp:Content ID="Content1" ContentPlaceHolderID="cphContent" Runat="Server">
    
      <asp:ScriptManager runat="server"/>
    
    
      <asp:UpdatePanel runat="server" id="upUpdatPanel">
        <ContentTemplate>
    
          <asp:TextBox runat="server" id="tbHtmlEditor" TextMode="MultiLine">
            Default editor text
          </asp:TextBox>
    
          <asp:Dropdownlist runat="server" ID="ddlTest" AutoPostBack="true" OnSelectedIndexChanged="ddlTest_SelectedIndexChanged">
            <Items>
               <asp:ListItem Text="A"></asp:ListItem>
               <asp:ListItem Text="B"></asp:ListItem>
            </Items>
          </asp:Dropdownlist>
    
          <asp:Button runat="server" ID="butSaveEditorContent" OnClick="butSaveEditorContent_Click" Text="Save Html Content"/>      
    
        </ContentTemplate>
      </asp:UpdatePanel>
    
      <script type="text/javascript">
    
          $(document).ready(function () {
            /* initial load of editor */
            LoadTinyMCE();
          });
    
          /* wire-up an event to re-add the editor */     
          Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler_Page);
    
          /* fire this event to remove the existing editor and re-initialize it*/
          function EndRequestHandler_Page(sender, args) {
            //1. Remove the existing TinyMCE instance of TinyMCE
            tinymce.remove( "#<%=tbHtmlEditor.ClientID%>");
            //2. Re-init the TinyMCE editor
            LoadTinyMCE();
          }
    
          function BeforePostback() {
            tinymce.triggerSave();
          }
    
          function LoadTinyMCE() {
    
            /* initialize the TinyMCE editor */
            tinymce.init({
              selector: "#<%=tbHtmlEditor.ClientID%>",
              plugins: "link, autolink",
              default_link_target: "_blank",
              toolbar: "undo redo | bold italic | link unlink | cut copy paste | bullist numlist",
              menubar: false,
              statusbar: false
            });
          }
    
      </script>
    
    
    
    
    </asp:Content>
    

    The Code-Behind:

        using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    public partial class TinyMCE : System.Web.UI.Page
    {
      protected void Page_Load(object sender, EventArgs e)
      {
        // we have to tell the editor to re-save the date on Submit 
        if (!ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
        {
          ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "SaveTextBoxBeforePostBack", "SaveTextBoxBeforePostBack()");
        }
    
      }
    
      protected void butSaveEditorContent_Click(object sender, EventArgs e)
      {
        string htmlEncoded = WebUtility.HtmlEncode(tbHtmlEditor.Text);
    
      }
    
      private void SaveToDb(string htmlEncoded)
      {
        /// save to database column
      }
    
      protected void ddlTest_SelectedIndexChanged(object sender, EventArgs e)
      {
    
      }
    }
    
    0 讨论(0)
  • 2021-02-07 13:44

    This is an old question, but after hours searching and messing around looking for the answer, I feel obligated to post the solution I came up with.

    It appears that, at least in the implementation I'm using (multiple editors inside an UpdatePanel) that tinyMCE must be informed the control is going away when the UpdatePanel submits, or else it will refuse to load it again.

    So, in addition to the code to Init TinyMCE (which only needs to run when the whole page loads) you need to do this for each of your MCE textboxes:

    ScriptManager.RegisterStartupScript(this, this.GetType(), elm1.UniqueID+"Add",
        "tinyMCE.execCommand('mceAddControl', true,'" + elm1.ClientID + "');", true);
    ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), elm1.UniqueID + "Remove",
        "tinyMCE.execCommand('mceRemoveControl', true,'" + elm1.ClientID + "');");
    

    elm1 is whatever the tinyMCE element is. Mine is a textarea residing in a UserControl, but you can apply it to any item you want to bind/unbind your textarea.

    0 讨论(0)
  • 2021-02-07 13:47

    You have to call the initializing method of the TinyMCE whenever the update panel is refreshed.

    For this, you have either to call this method (tinyMCE.init) from a RegisterStartupScript method, or to create a page load javascript function in the head section of the page like this:

    function pageLoad() {
       tinyMCE.init();
    }
    

    This function will be executed each time the update panel is refreshed.

    0 讨论(0)
  • 2021-02-07 13:47

    I di this

    <script language="javascript" type="text/javascript">
        function pageLoad(sender, args) { 
            aplicartinyMCE();     
        }
        function aplicartinyMCE() {
           tinyMCE.init({
               mode: "specific_textareas",
               editor_selector: "mceEditor",
               .....
           });
        }
    </script>
    

    That initialize the editor after each asynchronous postback even if

    Then in page_load event

    ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "salvarEditorMCE", "tinyMCE.triggerSave();");
    
    0 讨论(0)
  • 2021-02-07 13:50

    The correct way to make tinyMCE work in an updatepanel:

    1) Create a handler for the OnClientClick of your "submit" button.

    2) Run tinyMCE.execCommand("mceRemoveControl", false, '<%= txtMCE.ClientID %>'); in the handler, so as to remove the tinyMCE instance before the postback.

    3) In your async postback, use the ScriptManager.RegisterStartupScript to run tinyMCE.execCommand("mceAddControl", true, '<%= txtMCE.ClientID %>');

    Basically, all you need to do is use the mceRemoveControl command before the async postback and register a startup script to run the mceAddControl command after the async postback. Not too tough.

    0 讨论(0)
  • 2021-02-07 13:52

    Ok, your problem is two fold. Stefy supplied you with part of the answer, which is you have to initialize TinyMCE on the postback by registering startup script like so:

    using System.Web.UI;
    
    namespace TinyMCEProblemDemo
    {
        public partial class EditorClean : UserControl
        {
            protected void Page_Load(object sender, System.EventArgs e)
            {                
                  ScriptManager.RegisterStartupScript(this.Page, 
                      this.Page.GetType(), mce.ClientID, "callInt" + mce.ClientID + "();", true);
            }
        }
    }
    

    The second problem you have is with your implementation of a custom control. Designing custom controls is out of scope of this answer. Google can help you there.

    You have multiple instances of your control on the page which can cause you issues with script, as it get rendered multiple times. This is how I modified your markup to solve your issue(notice dynamic naming of your script functions, custom controls should be self contained and mode: "exact" on the tinyMCE.init):

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EditorClean.ascx.cs"
        Inherits="TinyMCEProblemDemo.EditorClean" %>
    <script type="text/javascript" src="Editor/tiny_mce.js"></script>
    
    <script type="text/javascript">
        function myCustomCleanup<%= mce.ClientID%>(type, value) {
            if (type == "insert_to_editor") {
                value = value.replace(/&lt;/gi, "<");
                value = value.replace(/&gt;/gi, ">");
            }
            return value;
        }
        function myCustomSaveContent<%= mce.ClientID%>(element_id, html, body) {
            html = html.replace(/</gi, "&lt;");
            html = html.replace(/>/gi, "&gt;");
            return html;
        }
    
        function callInt<%= mce.ClientID%>() {
    
            tinyMCE.init({
                mode: "exact",
                elements: "<%= mce.ClientID%>",
                theme: "advanced",
                skin: "o2k7",
                plugins: "inlinepopups,paste,safari",
                theme_advanced_buttons1: "fontselect,fontsizeselect,|,forecolor,backcolor,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent,blockquote,|,cut,copy,paste,pastetext,pasteword",
                theme_advanced_buttons2: "",
                theme_advanced_buttons3: "",
                theme_advanced_toolbar_location: "top",
                theme_advanced_toolbar_align: "left",
                cleanup_callback: "myCustomCleanup<%= mce.ClientID%>",
                save_callback: "myCustomSaveContent<%= mce.ClientID%>"
            });
        }
    </script>
    <textarea runat="server" id="mce" name="editor" cols="50" rows="15">Enter your text here...</textarea>
    
    0 讨论(0)
提交回复
热议问题