I have a page with a table, bound with Knockout inside an UpdatePanel. My goal is to get the binding successfully applied after a postback. Everything works as expected on initial page load, so the model is working.
I'm using pageLoad() to call a function that gets the model's JSON data from a HiddenField that was set server side. In the view I have each RadioButton's click data-bind set to a JS function outside the ViewModel that sets a hidden input field's value to the ID specified by the button, and then causes a server postback by clicking a hidden button client-side.
Inside pageLoad() I'm using Sys.WebForms.PageRequestManager.getInstance().add_endRequest to specify that the binding helper function should be called after the server-side of the postback is complete.
My problems:
After being set server-side, the HiddenField with the JSON data still has the same string as it did client-side when it returns to the client, even though when the server-side scriptlet is executed, I can see that the value updated correctly. Not sure what is going on here.
Even if the values don't update, BindingHelper() is called, although for some reason clicking on the RadioButtons no longer causes the event after one postback has already occurred.
Any insight into this would be greatly appreciated!
Code:
<script type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(BindingHelper)
function pageLoad() {
if (!isPostBack()){
BindingHelper();
}
}
function BindingHelper() {
var data = <%= hfData.Value%>;
var model = new DataViewModel();
model.load(data);
ko.applyBindings(model);
}
function Select(id) {
document.getElementById('<%=hfSelectedID.ClientID%>').value = id;
document.getElementById('<%=rbSelect.ClientID%>').click();
}
function isPostBack() {
return document.getElementById('hfPostback').value == 'True';
}
</script>
HTML:
<table id="tblData">
<thead>
<tr>
<th></th>
<!-- ko foreach: subViewModel -->
<th><input type="radio" name="rbGroup" data-bind="value: id, checked: $root.selectedID, click: function() {Select(id);}" /><span data-bind="text: name"></span></th>
<!-- /ko -->
</tr>
</thead>
</table>
<asp:HiddenField ID="hfData" runat="server" />
<asp:HiddenField ID="hfSelectedID" runat="server" />
<input id="hfPostback" type="hidden" value="<%=Page.IsPostBack.ToString()%>" />
<div style="display:none">
<asp:RadioButton ID="rbSelect" runat ="server" AutoPostBack="true" />
</div>
Edit: I've since determined that this works if the binding is not inside an UpdatePanel, just by registering BindingHelper() as a startup script in Page_Load.
Oddly enough, even if I register the startup script by specifying the UpdatePanel, the results are the same. There are other controls in the UpdatePanel so I know the UpdatePanel is in fact, updating, and it isn't set to conditionally update.
I solved this. I ended up needing to find the HiddenField in the DOM and then parsing the JSON from that to get the data for the model. It seems weird to me that even after the value had been set server-side, it was keeping the old value, but the UpdatePanel complicates the lifecycle.
Also I changed the RadioButton that is clicked client-side to a LinkButton to get it to always force a postback to the server.
Related
I am trying to invoke a server side method through JavaScript by first displaying a confirm message and then trigger a button click on the page to call the function. However, the .click() method doesn't seem to work. Any ideas?
<script type="text/javascript">
function confirmDelete() {
var button = document.getElementById("hiddenButton");
if (confirm("Are you sure you would like to delete the row")) {
button.click();
}
}
</script>
and the button is defined like follows
<asp:Button ID="hiddenButton" runat="server" onclick="showHiddenMessage" Text="hidden" width="100px" />
Everything that I have found suggest that it should. including here:
http://www.comptechdoc.org/independent/web/cgi/javamanual/javabutton.html
and here:
Call ASP.NET function from JavaScript?
var button = document.getElementById('<% =hiddenButton.ClientID %>');
Id of server side controls is different on client side. modify code as above and try.
Modify confirmDelete() method as below:
function confirmDelete() {
if (confirm("Are you sure you would like to delete the row")) {
__doPostBack(( 'hiddenButton', '' );
}
}
Take a look at the ClientIDMode property of a Button. Setting this to Static will cause the button to render with the ID you entered in to your ASP.NET code. https://msdn.microsoft.com/en-us/library/system.web.ui.control.clientidmode.aspx
<asp:Button ID="hiddenButton" runat="server" ClientIDMode="Static" onclick="showHiddenMessage" Text="hidden" width="100px" />
If you look at the generated HTML, you should see the ID of this button as hiddenButton which should allow your Javascript to work.
By default ClientIDMode value will be Inherit, and will include the NamingContainer within the ID. This means the ID of the rendered HTML will be something like Panel1_hiddenButton and your Javascript won't find it with the current code.
For reference:
Static - The ClientID value is set to the value of the ID property. If the control is a naming container, the control is used as the top of the hierarchy of naming containers for any controls that it contains.
Inherit - The control inherits the ClientIDMode setting of its NamingContainer control.
But why don't you use your javascript function with your button? I think it is better:
<script type="text/javascript">
function confirmDelete() {
if (confirm("Are you sure you would like to delete the row?")) {
return true;
}
return false;
}
And your button:
<asp:Button ID="hiddenButton" runat="server" OnClientClick="return confirmDelete();" onclick="showHiddenMessage" Text="hidden" width="100px" />
In this case if user will click OK button, your showHiddenMessage function will occur. Otherwise nothing will be happen.
I hope I will be able to explain my problem clearly.
Scenario:
Asp.net web page with UpdatePanel. Some properties of controls are changeable via UI trigger and are set in jQuery (for faster response, as this page is expected to accept input data of at least 500 records per day).
Example below, (if written in c# code, the logic is like this: txtIDNumber.Enabled = chkIsReceiptRequired.Checked; rfvIDNumber.Enabled = chkIsReceiptRequired.Checked;):
Markup:
<asp:CheckBox ID="chkReceiptRequired" runat="server" Text="Receipt required" />
<asp:TextBox runat="server" ID="txtIDNumber" Width="150px" style="float: left;" />
<asp:RequiredFieldValidator ID="rfvIDNumber" runat="server" ForeColor="Red"
ErrorMessage="Enter ID No." ControlToValidate="txtIDNumber" ValidationGroup="save" />
Snippet of default jQuery code (upon page load, chkReceiptRequired is unchecked, validator and textbox will only be enabled upon ticking chkReceiptRequired):
<script type="text/javascript">
function pageLoad(){
$('input[id$=_txtIDNumber]').prop('disabled', true);
ValidatorEnable($("[id$='rfvIDNumber']")[0], false);
$('input[id$=_chkReceiptRequired]').change(function () {
$('input[id$=_txtIDNumber]').prop('disabled', !$(this).is(':checked'));
$('input[id$=_txtIDNumber]').val(!$(this).is(':checked') ? '' : $('input[id$=_txtIDNumber]').val());
ValidatorEnable($("[id$='rfvIDNumber']")[0], $(this).is(':checked'));
});
}
</script>
I'm using this same page to load the data here to perform record update. Code snippet of data loading:
var maintableComponent = new MainTableComponent();
var maintableData = maintableComponent.GetMainTableDataById(rowId);
chkReceiptRequired.Checked = maintableData.IsReceiptRequired.Value;
txtIDNumber.Text = maintableData.IDNumber;
//todo: enable txtIDNumber and rfvIDNumber from here
The problem: by right, upon page render for update, because chkReceiptRequired is checked, supposedly txtIDNumber should be enabled. But my problem is, it is not. What can I do to enable the txtIDNumber and rfvIDNumber upon data loading from code-behind?
*I have already tried this link and this but it doesn't seem to work.
Please, please help me. The snippets I posted here are just one of many jQuery validations that I desperately need to address. Thanks in advance.
Feeling incredibly stupid right now. Figured out how to fix it after sleeping it off. :P
I just changed the default jQuery code to this:
var isReceiptRequired = $('input[id$=_chkReceiptRequired]').is(':checked');
$('input[id$=_txtIDNumber]').prop('disabled', !isReceiptRequired);
ValidatorEnable($("[id$='rfvIDNumber']")[0], isReceiptRequired);
I just remembered that the last thing in the page-cycle is rendering it on the page so the jQuery can be manipulated by the values set in the control from code-behind.
I'm using ASP.NET to pass a value to a JavaScript function and, for some reason I haven't been able to determine, it isn't working when I try to pass in a value from another control. Instead, it acts like there is a syntax error and it just submits back to the main form.
Does anyone know why?
Example:
<asp:TextBox ID="txtToSay" runat="server" Text="Something"></asp:TextBox>
<asp:Button runat="server" ID="btnSaySomething1" Text="Say Something"
OnClientClick="saySomething(<%=txtToSay.Text%>);" /> <!-- doesn't work -->
<asp:Button runat="server" ID="btnSaySomething1" Text="Say Something"
OnClientClick="saySomething('<%=txtToSay.Text%>');" /> <!-- doesn't work -->
<asp:Button runat="server" ID="btnSaySomething2" Text="Say Something"
OnClientClick="saySomething('Something');" /> <!-- works -->
<script type="text/javascript">
function saySomething(txt){
alert(txt);
};
</script>
Additional Information:
Web Application running on .NET 4.0
Language: C#
Update:
After working with this a while, I've determined that you can't use <%%> tags in ASP controls. Additionally, if you're looking for dynamic evaluation of control values AVOID AVOID AVOID using <%=someControl.Text%> or similar constructs since they are only evaluated once a request is submitted to the server. If you need a static value from another control at runtime, simply set that value in the page load event or handle it another way in the code behind.
Javacript will search for variable name = txtToSay.Text in saySomething function call, Put quotes around it to make it string value
Change
OnClientClick="saySomething(<%=txtToSay.Text%>);"
To
OnClientClick="saySomething('<%=txtToSay.Text%>');"
You can get the txtToSay.Text without passing it this way
<script type="text/javascript">
function saySomething(txt){
alert(document.getElementById('<%=txtToSay.Text%>').value);
};
</script>
you need to put ' around your text in the saySomething() call.
Like this:
<asp:Button runat="server" ID="btnSaySomething1" Text="Say Something" OnClientClick="saySomething('<%=txtToSay.Text%>');" />
UPDATE
<%= %> won't work inside an asp.net control. Can you set it from the code-behind?
I.E
btnSaySomething1.OnClientClick = "Text to say"
I have code like this
<table>
<tr>
<td>
<div>
<asp:Label runat="server" ID="lblBookmarksIds" Style="visibility: hidden;" Text="test"/>
</div>
</td>
<td>
<asp:UpdatePanel runat="server" ID="buttonPanel" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button runat="server" ID="btnInvokeImageRead" CausesValidation="false" UseSubmitBehavior="false"
OnClick="btnInvokeImageRead_Click" Style="visibility: hidden;" />
</ContentTemplate>
</asp:UpdatePanel>
</td>
</tr>
</table>
in javascript i'm trying to set value of label and call codebehind function so that i will have desired value passed to codebehind like that :
alert(document.getElementById('<%= lblBookmarksIds.ClientID%>').firstChild.nodeValue);
document.getElementById('<%= lblBookmarksIds.ClientID%>').innerText = str;
alert(document.getElementById('<%= lblBookmarksIds.ClientID%>').firstChild.nodeValue);
//alert('1');
if (str != "") {
document.getElementById('<%= btnInvokeImageRead.ClientID%>').click();
}
when second alert gets displayed the value of lblBookmarksIds has changed value, but when i debug in codebehind function btnInvokeImageRead_Click the value of lblBookmarksIds has its old value.
Anybody knows Why ?
Regards
Wojciech
Labels are not passed to code behind. You will have to use an input(TextBox) for that purpose.
You can style an input to look like a label using CSS.
Alternatively, you can keep the value in a hidden field, and use javascript to show the value in a label and pass it back in the hidden field.
The reason ASP.NET is able to "see" the values entered into a TextBox and similar controls is because the values of these controls are sent in the POST body when the page posts back. You can see this through any number of tools, including the Developer Tools your browser likely includes or an intercepting proxy like Fiddler. When the postback occurs, each of those controls has a LoadPostData function that processes the POST data and updates the Text properties (or whatever properties) of the control.
The contents of a Label are not submitted in the POST data, so .NET has no way to see any changes made to it from JavaScript.
The controls that do process post data all implement IPostBackDataHandler.
I had created a checkbox at the server during runtime, and populated it in a table on the webpage, and I would like to make use of it to trigger some JavaScript to handle some functions in the client.
However, I'm not sure of how to trigger the function using a checkbox created in this manner.
I understand that I can trigger the function when I declare a checkbox in this syntax.
asp:CheckBox ID="Checkbox1" runat="server" Onclick="javascript:myfunction()"
However, this checkbox may or may not be required to be created on the webpage, and hence I'm unable to insert this hardcoded on the webpage
Is there any way which I can use to detect the status of this checkbox and trigger my JavaScript in the client? or if I can handle what I need to do at code_behind?
suppose that we are adding CheckBox to td of an table
<table>
<tr>
<td id="td1" runat="server">
</td>
</tr>
</table>
and in the code behind,
CheckBox chkbox = new CheckBox();
chkbox.ID = "CheckBox1";
chkbox.Attributes.Add("onclick", "click_Func(this);");
td1.Controls.Add(chkbox);
and javascript will be look like this ,
<script type="text/javascript">
function click_Func(chkbox) {
alert(chkbox.id);
}
</script>
you can add a script tag on the page like this
<script type="text/javascript">
$('#<%=Checkbox1.ClientID%>').live('changed',function(){
// Do your work here.
});
</script>