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.
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.
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();
});
Related
I have a formview which launches in editmode and allows the user to select yes or no from a dropdown and hit the 'save' button which is the Formviews Update command:
<asp:FormView ID="FormView1" runat="server" DataSourceID="CustomerEdit">
<ItemTemplate>
hello
</ItemTemplate>
<EditItemTemplate>
<asp:Label ID="CustomerNameLabel2" runat="server"
Text='<%# Bind("CustomerName") %>' />
<asp:Label ID="CustID" runat="server" visible="false"
Text='<%# Bind("CustID") %>' />
<br>
<br></br>
Is This Your Customer?
<br>
<br>
<asp:DropDownList ID="DropDownList1" runat="server"
SelectedValue='<%# Bind("IsThisMyCustomer") %>'>
<asp:ListItem Selected="True"></asp:ListItem>
<asp:ListItem>Yes</asp:ListItem>
<asp:ListItem>No</asp:ListItem>
</asp:DropDownList>
<br>
<br>
<asp:Button ID="Button" runat="server" CausesValidation="True"
CommandName="Update" Text="Save" />
</EditItemTemplate>
</asp:FormView>
This button also has JQuery behind it
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<script>
$(document).ready(function () {
$("input[id$='Button']").click(function () {
var div = $("div");
$("img").hide();
div.animate({ height: '300px', opacity: '0.4' }, "slow");
div.animate({ width: '300px', opacity: '0.8' }, "slow", function () {
window.location.href = "MyCustomers.aspx";
});
});
});
</script>
Now when the user hits the button, the Jquery script kicks in, then about halfway through the animation of the jquery script, the SQL update through the FormView Update command kicks in, essentially stopping jquery from doing its stuff and launching the itemtemplate of the formview as per a regular update.
What I want is the SQL update to occur and postback, then the jquery fire straight after.
What's the best approach to doing this
You're mixing client-side and server-side functionality. The order of events you're observing is this:
Load the page
Bind the click event to the element
Click the element (begins the animation)
Reload the page
Bind the click event to the element
Your click event is really only accomplishing one thing, redirecting the user to another page. If the page is being reloaded anyway, then why not do that from server-side code?
Response.Redirect("MyCustomers.aspx");
It doesn't have the animation, but since you're reloading the page anyway then the animation is kind of moot. If you want to have the animation then you probably don't want to reload the page, in which case you'll want to start looking into AJAX for interacting with the server from JavaScript code. (Which can be a pretty big subject, especially when dealing with WebForms controls. It's often better in that case to just "do it the WebForms way" and not try to mess with them.)
In your comment above, you said you tried this...
$(window).load(function () { $(document).ready(function () { ...
That's... not right. Don't just randomly mix and match jQuery code, understand what it is you're doing here. You're binding events (such as ready) inside of an event handler (such as load), which can get pretty strange pretty fast. Separate the event you want to respond to from the code you use to respond to it. For example, consider what you have here:
$("input[id$='Button']").click(function () {
//...
});
This doesn't execute the code inside the function, it binds that function to be executed when the click event happens. The same is true of this structure:
$(document).ready(function () {
$("input[id$='Button']").click(function () {
//...
});
});
This binds a function to be executed when the ready event happens. That function, in turn, binds another function to be executed when the click event happens.
Consider for example what I mentioned in my comment above... If you really want to animate the element and then redirect after the page reloads (which I still contend is a pretty poor UX, to be honest) then you would do this:
$(document).ready(function () {
var div = $("div");
$("img").hide();
div.animate({ height: '300px', opacity: '0.4' }, "slow");
div.animate({ width: '300px', opacity: '0.8' }, "slow", function () {
window.location.href = "MyCustomers.aspx";
});
});
This skips the click event and just sets that code to execute immediately on the ready event. Which means it'll execute when the page loads, basically. Which also means that you don't want to always include this in the page (otherwise you'd never be able to view the page for more than a moment). You'd want to only include it dynamically from the post-back which should cause this redirect.
Ultimately, you need to separate your client-side functionality from your server-side functionality. If you're just redirecting after a form post (which is what you're doing), then redirect from server-side code. If you want the bells and whistles of client-side animations and UX, don't use WebForms post-backs.
What I would like to do is be able to disable a button as soon as it pressed, perform an operation, and re-enable the button. Seemed simple enough, but my button doesn't update when I need it to. I tried an update panel, but I'm not sure if I'm using it correctly. Am I doing something wrong? Or is there a better way to achieve this?
HTML
<asp:UpdatePanel runat="server" ID="updateSubmitButton">
<ContentTemplate>
<asp:Button ID="btnSearch" CssClass="CrossoverButton" runat="server" Text="Search" OnClick="btnSearch_Click" />
</ContentTemplate>
</asp:UpdatePanel>
C#
protected void btnSearch_Click(object sender, EventArgs e)
{
btnSearch.Enabled = false;
updateContent();
// Do a lengthy operation here.
btnSearch.Enabled = true;
}
You will need to use a client side technology to disable the button. This is because when you click the button, the page does a post back to itself, which tells the server to execute btnSearch_Click. Based on your code this will
Disable the button
Update the content
Re-enable the button
all of this happens on the server. Only after the method has finished executing, does it return context to the page.
In order to disable the button on click, you'll want to try something this:
<asp:Button ID="btnSearch" CssClass="CrossoverButton" runat="server" Text="Search"
OnClientClick="this.disabled = true;"
UseSubmitBehavior="false" />
OnClientClick="this.disabled = true;"
This line registers the client click handler, to disable itself.
UseSubmitBehavior="false"
This line tells ASP.NET to include the disabled element in the form post, so the server knows which control registered the postback.
See also -- https://stackoverflow.com/a/11832053/86860
All the actions in btnSearch_Click will be performed on server. The page will not be rendered until full page lifecycle ends.
If you want to disable the button you should use javascript to do this, and then only after disabling the button make a postback to the page.
I have a page that above it I want to have a panel that automatically refresh every 5 minutes, and if a user has a message in his inbox show to him. What is the best solution for this?
Should I usel AJAX, jQuery, or JavaScript? My preferred solution is server side solution.
Since you are working with ASP.Net, you can also achieve this behavior by using a combination of the following:
ScriptManager or ScriptManagerProxy (if you have nested pages):
Manages the ajax calls
UpdatePanel: Determines what gets updated. Controls nested within <ContentTemplate> are subject to partial
updates
Triggers: Controls when the content is updated.
For your purpose, a Timer control can be used as a trigger to ensure that partial postbacks are triggered every 5 seconds:
<asp:ScriptManager ID="scriptManagerMain" runat="server"/>
<asp:Timer ID="timer" Interval="5000" runat="server"/>
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Panel ID="panelToBeUpdated" runat="server">
<asp:Label ID="lblContent" runat="server" ></asp:Label>
</asp:Panel>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="timer" />
</Triggers>
</asp:UpdatePanel>
I would use Jquery to send an AJax request to the server to fetch the updated content. Upon receiving the content I would use JQuery again to update the markup.
You can set this up to trigger every 5 min using setInterval in Javascript
Hard to give a specific example without code. But you basically need to load the new content with an ajax request that is triggered by a timer.
setInterval(function(){
$.ajax({
url: "someUrlThatServesUpdatedContent.aspx",
cache: false
}).done(function( html ) {
$("#results").html(html);
});
}, 300000);
The above is just a simple example to point you in the right direction.
Edit: Here is an example of how to do the ajax call without JQuery
https://stackoverflow.com/a/2792721/1059001
It's possible to do that with AJAX using method described by previous answers, but if you wish to have a server side solution I would recommend loading that part of the page in an iframe, with meta refresh:
<meta http-equiv="refresh" content="300">
This method however would make it difficult to communicate any events or user actions back to main page.
how to fill textbox in asp.net while i am typing in another text
.. changes in one textbox will affect in another textbox auto.. and without refreshing my page.
Ok, try this. You will need the AJAX Control Toolkit. So read the article Installing AJAX Control Toolkit 4 in Visual Studio 2010 to see how to install it in Visual Studio.
Then you need to add a ScriptManager to your ASPX page. You will need to add the following code:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
What you then need to do, is add an UpdatePanel to your page. Inside this update panel, you need to place the textbox. This means that only the controls inside the update panel will refresh, and not the whole page. To do this, add the following code:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<!--Add your Textbox Control to update here: Textbox1-->
<asp:TextBox ID="Textbox1" runat="server" ReadOnly="True"></asp:TextBox>
<asp:TextBox ID="Textbox2" runat="server" ReadOnly="True" ontextchanged="Textbox2_TextChanged"></asp:TextBox>
</ContentTemplate>
<Triggers>
<!--This is the textbox you will be typing text into: TextBox2-->
<asp:AsyncPostBackTrigger ControlID="Textbox2" EventName="TextChanged" />
</Triggers>
</asp:UpdatePanel>
The Trigger tells your page which control on the form needs to initiate the postback. Now in your .cs file, you need to add the event handler for the Textbox2 TextChanged event. Add the following code:
protected void Textbox2_TextChanged(object sender, EventArgs e)
{
// Set the text of textbox1 = textbox2
}
I hope that this helps.
No need for AJAX. JQuery is enough. The code will do it
$('#text1').bind('keyup', function(){
$('#text2').val($('#text1').val());
});
Assuming
text1 id of box writing into.
text2 textbox that text gets copied to
in .Net you will have to use client id to get the correct id so it may look like this
$('<%=text1.ClientID%>').bind('keyup', function(){
$('<%=text2.ClientID%>').val($('#text1').val());
});
Oh and wrap it up in $(document).ready as per standard. And of coures you need to include the JQuery library to your page.
No posting back or page refreshes at all. It's your lightest solution and easy to implement.
You will need to use Javascript to accomplish this. ASP.Net code runs on the server side, which means it cannot affect the page without a postback happening first. Read up on the OnTextChanged event and how to hook into it with javascript. There is a javascript library called jQuery which makes everything easier, though it isn't strictly necessary.
Use JQuery. You may need to make an AJAX call to the server if you are relying on a datasource such as a database to autofil this field.
I have two placeholders in one page and basically my requirement is that I want to show other placeholder on click of button which is in first placeholder without refreshing the page.
But when I m clicking on the button in 1st placeholder it is refreshing the page and then showing me second placeholder.I m open to hear any other suggestions also if it is not possible through placeholder.
Can anyone tell me how to achieve this?
Thanks,
You could, as suggested, use an UpdatePanel. As long as you ensure that both PlaceHolders exist within the ContentTemplate element, you will be able to switch between the PlaceHolders without the whole page being refreshed.
However, such convenience comes at the cost of control. This isn't a knock on Microsoft. The same problems exist for most ready-rolled solutions.
Whatever route you choose, you're going to need something to refresh part of the current page's DOM. And really, this means Javascript.
Do the actions in PlaceHolder 1 change the content of PlaceHolder 2? If not, you could render both, and simply use CSS to make PlaceHolder 2 invisible on load. You could then use Javascript events to make it visible as desired.
If actions on PlaceHolder 1 do affect PlaceHolder 2, then the above solution won't work, as you'll need to work out what PlaceHolder 2 is going to contain before displaying it.
The real question is whether you employ your own Javascript ( possibly in conjunction with a mature js library like mootools or jQuery ), and maybe learn something in the process, or run with the ASP .NET AJAX stuff for the quick solution, and hope you don't run into any problems.
You could wrap an updatepanel around you PlaceHolder:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:PlaceHolder runat="server" ID="placeholder">hello</asp:PlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
Codebehind:
protected void Page_Load(object sender, EventArgs e)
{
placeholder.Visible = false;
}
protected void Button1_Click(object sender, EventArgs e)
{
placeholder.Visible = true;
}
This wil generate a partial postback (via AJAX), so only the content inside my updatepanel gets updated. In the <Triggers>-section, I specify that my Button will trigger the postback.
Either use an UpdatePanel control (part of the MS ajax framework) or use JavaScript. Placeholder would have to render an HTML element, and I'm not sure that it does. If it doesn't, you can use a panel instead, and then in JS do:
function show() {
var panel = document.getElementById("<%= panel2.ClientID %>");
panel.style.display = "true";
}
<asp:Button id="btn1" runat="server" OnClientClick="show();return false;" />
HTH.