Scenario
As part of a "View case" page there should be a function to add a new case note.
A case note can be "visible externally" with the option to provide different 'external' text.
What I have done, is to use a ModalPopupExtender
from the ASP.NET Ajax Control Toolkit which fires when the 'Add note' button is clicked, to show a panel with a textbox to enter the new note. There is a CheckBox
underneath the textbox which the user can tick if the note is available externally.
When ticked, some jQuery should fire, which fades in the 'public note content' box and pre-sets it to the value of the 'note content' text box.
Once the public text is entered, the user should click 'Save note'. The note is written to the database, the GridView
of notes is rebound and the ModalPopup hides.
The jQuery is referenced once, on Page_Load
as follows.
ScriptManager.RegisterClientScriptInclude(Me, Me.GetType, "BensJQuery", Page.ResolveUrl("~/include/BensJquery.js"))
Problem:
The user might then want to add a second note. They click 'Add note' again, the ModalPopupExtender
shows the modal popup again. This time, if they click the 'Available externally' checkbox, the jQuery does NOT fire. The public note content area does not show. The test alert()
does not show.
The same problem happens if the user clicks 'Cancel' and does not actually add a note. The ModalPopup will disappear but then they cannot use it properly if they try to subsequently add a note.
Markup
<asp:UpdatePanel ID="updNotes" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:GridView ID="gvNotes" runat="server" AllowPaging="true" PageSize="10" AutoGenerateColumns="false" Width="100%">
<PagerSettings Mode="NumericFirstLast" Position="TopAndBottom" />
<Columns>
<asp:BoundField HeaderText="Date" DataField="CreationDate" />
<asp:BoundField HeaderText="Author" DataField="CreatedBy" />
<asp:BoundField HeaderText="Note" DataField="Text" ItemStyle-Width="80%" />
</Columns>
</asp:GridView>
<p><asp:Button ID="btnAddNewNote" runat="server" Text="Add note" CssClass="addButton" CausesValidation="false" /></p>
<asp:Panel ID="pnlNewNote" runat="server" GroupingText="New note" style="display: none;" CssClass="mdlPopupPanel">
<p>To add a new note, enter the note information here and click 'Add note'</p>
<scc:TextBox runat="server" ID="txtNewNoteContent" TextMode="MultiLine" CssClass="mainNoteContent input"
Rows="6" Width="75%" Label="Text" ValidationGroup="NewNote" />
<p>
<asp:CheckBox ID="chkMakeAvailExternally" CssClass="chkAvailExternally" runat="server" />
<asp:Label runat="server" Text=" Note is available to public" AssociatedControlID="chkMakeAvailExternally" />
</p>
<div class="publicNoteContent" style="display: none;">
<scc:TextBox ID="txtPublicNoteContent" runat="server" Label="Text to show to public"
TextMode="MultiLine" Rows="6" Width="75%" CssClass="publicNoteContent input" Required="false" />
</div>
<p>
<asp:Button ID="btnSaveNote" runat="server" CssClass="confirmButton" Text="Save note" ValidationGroup="NewNote" />
<asp:Button ID="btnCancelAddNote" runat="server" CssClass="cancelButton" Text="Cancel" CausesValidation="false" />
</p>
</asp:Panel>
<act:ModalPopupExtender ID="mpopNewNote" runat="server" TargetControlID="btnAddNewNote" PopupControlID="pnlNewNote" />
</ContentTemplate>
</asp:UpdatePanel>
jQuery
$(document).ready(function () {
$(".chkAvailExternally").click(function (event) {
alert('test'); // This alert displays for the first note added but not subsequent notes
var publicNoteDiv = $(this).parent().parent().find('div.publicNoteContent');
if (publicNoteDiv.is(":visible")) {
publicNoteDiv.fadeOut();
}
else {
var existingText = publicNoteDiv.parent().find('textarea.mainNoteContent').text();
if (publicNoteDiv.find('textarea.publicNoteContent').text() == '') {
publicNoteDiv.find('textarea.publicNoteContent').text(existingText);
}
publicNoteDiv.fadeIn();
}
});
});
Code-behind
Protected Sub btnSaveNote_Click(sender As Object, e As System.EventArgs) Handles btnSaveNote.Click
Dim CaseRef As String = Request("CaseReference")
Using ctx As New CAMSEntities
Dim c As [Case] = ctx.Cases.Single(Function(x) x.Reference = CaseRef)
c.AddNote(txtNewNoteContent.Text, chkMakeAvailExternally.Checked, txtPublicNoteContent.Text)
ctx.SaveChanges()
gvNotes.DataSource = c.Notes.OrderByDescending(Function(x) x.CreationDate).ToList
gvNotes.DataBind()
txtNewNoteContent.Text = String.Empty
chkMakeAvailExternally.Checked = False
txtPublicNoteContent.Text = String.Empty
End Using
End Sub
Instead of using $(".chkAvailExternally").click(
directly, use $(".chkAvailExternally").live("click",function(){.
.
Read about it here and here. Basically the second time for the modal popup, the elements are not part of DOM anymore, so you have to attach an event handler for those.
Update: After reading some more on it, perhaps you would be better off using a delegate
instead of live
to reduce the scope. More info here.