Sandeep Aparajit
Sandeep Aparajit

Reputation: 45

CodeMirror with UpdatePanel in asp.net

I'm using CodeMirror in an ASP.NET web application. The web app uses UpdatePanel (ajax). In ajax postback, I'm not able to get updated text from the CodeMirror textbox on server side and after the postback, the text gets reset. This WORKS if I don't use an update panel. What am I missing?

Below is the code mirror code:

 editor = CodeMirror.fromTextArea(document.getElementById("<%=txtLua.ClientID%>"), {
                matchBrackets: true,
                theme: "neat",
                pollInterval: 100,
                continuousScanning: 500
            });

<asp:UpdatePanel ID="upd" runat="server">
        <ContentTemplate>
            <asp:TextBox runat="server" ID="txtLua" Height="320" Width="600" TextMode="MultiLine"></asp:TextBox>
            <asp:Button ID="btn" runat="server" OnClick="btn_Click" Text="btn" />
        </ContentTemplate>
</asp:UpdatePanel>

Is there an asp.net/C# sample for using CodeMirror? Any help is appreciated.

Upvotes: 2

Views: 1410

Answers (2)

Sue Maurizio
Sue Maurizio

Reputation: 702

This is how I managed to make it work, just in case someone else needs it. After instantiating editor, I'm keeping the textbox aligned every time the blur event occurs.

editor.on('blur', function () {
    arguments[0].save();
});

Upvotes: 2

GunnerGuyven
GunnerGuyven

Reputation: 551

The short answer is: create a javascript event hook that fires early (before the UpdatePanel begins to do its work) and manually calls CodeMirror's .save() function.

The problem seems to arise because the auto-magic form.submit override that CodeMirror supplies is triggered after the ScriptManager has already passed the ViewState of the panel back to the server. This means the server only receives the TextBox in its initial state (CodeMirror hasn't put what you've typed into it yet). I checked the DOM events in Chrome and ScriptManager's hook was consistently ahead of the form.submit override that CodeMirror added.

I got around this by adding an .onclick to the submit button right after CodeMirror loaded. Using your example:

var editor = CodeMirror.fromTextArea(document.getElementById("<%=txtLua.ClientID%>"), {
            leaveSubmitMethodAlone: true,  //since you don't need this anymore, no reason to complicate your DOM
            matchBrackets: true,
            theme: "neat",
            pollInterval: 100,
            continuousScanning: 500
        });
window['cmLocalStateEvent'] = function () { editor.save(); };
//saveButton = document.getElementById("<%=btn.ClientID%>");  //grab the save button
//if (saveButton) {
//    saveButton.onclick = function () { editor.save(); };  //make it do what the submit action was going to do 
//}

<asp:UpdatePanel ID="upd" runat="server">
    <ContentTemplate>
        <asp:TextBox runat="server" ID="txtLua" Height="320" Width="600" TextMode="MultiLine"></asp:TextBox>
        <asp:Button ID="btn" runat="server" OnClientClick="if(window['cmLocalStateEvent'])window.cmLocalStateEvent();" OnClick="btn_Click" Text="btn" />
    </ContentTemplate>
</asp:UpdatePanel>

Now the .onclick is ahead of the ScriptManager hook, and will fire first. Infact, if you put an OnTextChanged= and AutoPostBack= on the TextBox it'll fire even before the button that you just clicked does.

Essentially, the trick is to get CodeMirror's save to apply before ScriptManager submits the ViewState back to the server.

EDIT: I've found since posting this, that you'll run into a troublesome issue if your submit button is also inside the UpdatePanel (which yours is). The .onclick will not persist after the initial submit and you'll be reset to a clean button with no event hooks. My current working solution to that scenario is adding a window['cmLocalSaveEvent'] function and adding the client .onclick to the ASP template (so the panel refresh puts it back for you). Updated code above to reflect this.

Upvotes: 2

Related Questions