Javascript variables in asp.net usercontrols - overwriting variables in same inserted usercontrol - javascript

I have four same UserControls inserted into Default.aspx. I want to write the data into HiddenField and write this data into Label1 using javascript.
The method only works for the last loaded UserControl - HiddenFieldLoader3.
Why the method does not work in all usercontrols? How can i fix my code?
Default.aspx
<%# Register Src="~/HiddenFieldLoader.ascx" TagPrefix="uc1" TagName="HiddenFieldLoader" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Default.aspx</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="HiddenFieldLoader.js"></script>
</head>
<body>
<form id="form1" runat="server">
<uc1:HiddenFieldLoader runat="server" ID="HiddenFieldLoader" />
<uc1:HiddenFieldLoader runat="server" ID="HiddenFieldLoader1" />
<uc1:HiddenFieldLoader runat="server" ID="HiddenFieldLoader2" />
<uc1:HiddenFieldLoader runat="server" ID="HiddenFieldLoader3" />
</form>
</body>
</html>
UserControl: HiddenFieldLoader.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="HiddenFieldLoader.ascx.cs" Inherits="NewControls.HiddenFieldLoader" %>
<script type="text/javascript">
HFLoader.declareVariables("<%=Button1.ClientID %>", "<%=HiddenField1.ClientID %>", "<%=Label1.ClientID %>");
</script>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<asp:HiddenField ID="HiddenField1" runat="server" />
<input type="button" ID="Button1" value="Save" runat="server" />
<input type="button" ID="Button2" onclick="HFLoader.showEvent();" value="Show" runat="server" />
Javascript file: HiddenFieldLoader.js
HFLoader = {
button: null,
hiddenField: null,
label: null,
declareVariables: function (btn, hf, label) {
HFLoader.button = btn;
HFLoader.hiddenField = hf;
HFLoader.label = label;
},
///////SHOW EVENT
showEvent: function () {
$("#" + HFLoader.label).html($("#" + HFLoader.hiddenField).val());
},
//////!SHOW EVENT
saveHiddenField: function (data) {
$("#" + HFLoader.hiddenField).val(data);
},
buttons: function () {
$("#" + HFLoader.button).click(function () {
var datatest = "Data from button ID: " + $(this).attr("id");
HFLoader.saveHiddenField(datatest);
$("#" + HFLoader.label).html($("#" + HFLoader.hiddenField).val());
return false;
});
},
init: function () {
$(function () {
HFLoader.buttons();
});
}
};
HFLoader.init();

It doesn't work because you're using a single instance variable, HFLoader, and not an instance.
So one way to fix it is to wrap your HFLoader in a closer (function, local scope) so that the object is scoped per method call. In the example below, I wrapped the HFLoader variable in a creator function. Then, each call to HFLoaderCreator will produce a different version (instance) of the HFLoader object. The reason I chose to do it this way instead of creating a true JS class was because it required minimal code changes to demonstrate how it could be done.
Edit. Let's also say you want to recall the HFLoader at a later date to call on things, such as the saveHiddenField method. To do this, I've done 2 this. 1) I've added data('HFLoader') to the three elements passed in, so you can use any one of them to recall the HFLoader settings. And 2) I've added custom events that you can trigger to call the methods. These two options show two different ways that jQuery plugin developers use to allow access to underlying structures.
<script type="text/javascript">
HFLoaderCreator("<%=Button1.ClientID %>", "<%=HiddenField1.ClientID %>", "<%=Label1.ClientID %>");
</script>
function HFLoaderCreator(btn, hf, label)
{
var HFLoader = {
button: null,
hiddenField: null,
label: null,
declareVariables: function (btn, hf, label) {
HFLoader.button = btn;
HFLoader.hiddenField = hf;
HFLoader.label = label;
},
saveHiddenField: function (data) {
$("#" + HFLoader.hiddenField).val(data);
},
buttons: function () {
$("#" + HFLoader.button).click(function () {
var datatest = "Data from button ID: " + $(this).attr("id");
HFLoader.saveHiddenField(datatest);
$("#" + HFLoader.label).html($("#" + HFLoader.hiddenField).val());
return false;
});
// add the data so it can be recalled at a later date
$("#" + HFLoader.button).data('HFLoader', HFLoader);
$("#" + HFLoader.hiddenField).data('HFLoader', HFLoader);
$("#" + HFLoader.label).data('HFLoader', HFLoader);
// add custom event handlers - saveHiddenField
$("#" + HFLoader.button).on('saveHiddenField', HFLoader.saveHiddenField);
$("#" + HFLoader.hiddenField).on('saveHiddenField', HFLoader.saveHiddenField);
$("#" + HFLoader.label).on('saveHiddenField', HFLoader.saveHiddenField);
// add custom event handlers - showEvent
$("#" + HFLoader.button).on('showEvent', HFLoader.showEvent);
$("#" + HFLoader.hiddenField).on('showEvent', HFLoader.showEvent);
$("#" + HFLoader.label).on('showEvent', HFLoader.showEvent);
},
init: function () {
$(function () {
HFLoader.buttons();
});
}
};
HFLoader.declareVariables(btn, hf, label);
HFLoader.init();
return HFLoader;
}
So now to make use of it all. In JS, if you wanted to look up the HFLoader data based on the Button1 ID, you might do something like this:
<script type="text/javascript">
var HFLoader = $('#<%=Button1.ClientID %>').data('HFLoader');
HFLoader.showEvent();
</script>
If you wanted to use ButtonID1 to trigger the custom event, which would ultimately call the showEvent method, you could do:
<script type="text/javascript">
$('#<%=Button1.ClientID %>').trigger('showEvent');
</script>
And if you wanted to do it inline, like your first example...
<input type="button" ID="Button2" onclick="$('#<%=Button1.ClientID %>').data('HFLoader').showEvent();" value="Show" />
Although I'd highly recommend instead using JS to wire an event to Button2, such as:
$(function()
{
$('#<%=Button2.ClientID').click(function()
{
$('#<%=Button1.ClientID %>').data('HFLoader').showEvent();
return false;
});
});
That way it's not inline script. Overall, the script for HFLoader is a bit hacked together. I'd recommend taking a look at the examples I've put together to extract the pieces of useful information and consider rethinking and/or rewriting the way you're doing things. Your brain is pushing you towards some kind of "global" view, or some kind of automatically scoped variable called HFLoader. But if you have 5 instances on a page, then you really want instances of some HFLoader object and not some global concept of HFLoader. It's like creating a new instance of a class instead of using a static or singleton instance of a class -- two very different concepts!
I hope this helps.

Related

Activate javascript string onload on code behind C#

Good day!
I need a help on activating my javascript function via on-load on code behind.
Here is my code:
string script = #"var applyCss = function () {
var css = '#CalendarPanel1-month-day-20170607, #CalendarPanel1-month-day-20170614 {background-color: #D0D3D4;}';
Ext.net.ResourceMgr.registerCssClass('someCssClassId', css);
}; ";
ScriptManager.RegisterClientScriptBlock(this, typeof(Page), "css", script, true);
By the way, my code above works in front-end via button click.
But my desired result is, I want my javascript function to work on page load without needing to click the button. I put my javascript function in code-behind because I will put dynamic dates in the css variables. The code above still has static variables. (CalendarPanel1-month-day-20170607)
Will gladly appreaciate any response / solution. Big thanks!
You could use an immediately invoked function to do the trick. Basically you don't give a name to your javascript function and you invoke it right after it's defined.
For example:
var script = #"(function () {alert('Hello');})(); ";
ScriptManager.RegisterStartupScript(this, typeof(Page), "123", script, true);
You need to wrap the function with its body between parenthesis then another set of parenthesis to invoke the function.
You can also pass parameters to your function (which I'm assuming it's what you want to do):
var myAlertText = "Hello Hello";
var script = #"(function (myText) {alert(myText);})('" + myAlertText + "');" ;
If I were you though I would defined the function in client code and just invoke it from code behind with the right parameters.
An alternative and fancier way to call javascript code from code behind would be using X.Call(). Check out this example:
<%# Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
string script = #"var myJSSideVar = 'my var value';
var applyCss = function (paramOne, paramTwo) {
var css = '#CalendarPanel1-month-day-20170607, #CalendarPanel1-month-day-20170614 {background-color: #D0D3D4;}';
Ext.net.ResourceMgr.registerCssClass('someCssClassId', css);
Ext.Msg.alert('applyCss called.', 'I\'ve been run with parameters: (' + paramOne + ', ' + paramTwo + ').');
};";
var hi = "hello";
X.AddScript(script);
X.Call("applyCss", new object[] { hi, new JRawValue("myJSSideVar") });
}
}
</script>
<html>
<head runat="server">
<title></title>
</head>
<body>
<form runat="server" id="form1">
<div>
<ext:ResourceManager runat="server" />
</div>
</form>
</body>
</html>
Notice the second parameter sent to the script call is sent "raw", i.e., it calls: applyCss("hello", myJSSideVar)
If you need to pass but one single parameter you don't need to pass an array, e.g. X.Call("applyCss", hi);

Why asp hidden field are not getting set from client side ?

I am using javascript to set asp:hiddenfield to '1' but not getting set.
I am setting it like this:
<script type="text/javascript">
function uploadComplete(sender, args) {
var myHidden = document.getElementById('<%= HdnFieldEmployeePicture.ClientID %>');
myHidden.value = '1';
}
</script>
from:
<asp:AsyncFileUpload ID="FileUpload1" OnClientUploadComplete="uploadComplete" ClientIDMode="AutoID" UploaderStyle="Modern" runat="server"/>
<asp:HiddenField ClientIDMode="Static" ID="HdnFieldHasFileUploaded" runat="server" />
I am checking it on server side:
if (HdnFieldHasFileUploaded.Value == "1")
{
but not set to 1.
AsyncControl and hidden field are inside UpdatePanel.
Your javascript code will not work because javascript method bindings get broken when your page is partially submitted using asp.net update panel. You need to add following lines of code to get it back to work.
<script type="text/javascript">
function EndRequestHandler(sender, args) {
// bind your methods here
}
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
</script>

VB call javascript resource code behind

I'm trying to pass a string and call a javascript function from the code behind in vb.net, once I click a button. The javascript is in a separate file.
Below is the code for the button:
/MyProject/myfile.aspx
<HTML>
...
...
<asp:textbox id="txtSearch" runat="server" Width="120px" CssClass="midField"></asp:textbox>
<input class="midBtn" id="btnSearch" type="button" value="Search" name="btnSearch" runat="server">
...
...
<script src='<%= Page.ResolveClientUrl("~/script/functions/myFunc.js")%>' ></script>
</HTML>
/MyProject/myfile.aspx.vb
Private Sub btnSearch_ServerClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.ServerClick
Dim searchString As String
searchString = txtSearch.Text
Dim rsname As String = Page.ResolveClientUrl("~/script/functions/myFunc.js")
Page.ClientScript.RegisterStartupScript(Me.GetType(), "mySearch", "mySearch('" & searchString & "')", True)
End Sub
/MyProject/script/functions/myFunc.js
function mySearch(searchString){
// ...
// logic for mySearch
// ...
}
I can't get the javascript function to be called and I need to reference the .js file at the end of my .apsx page. The error I get from the debugger is Uncaught ReferenceError: mySearch is not defined, please help.
If the criterion of choice is a dropdown, probably a better solution (I used jquery) is put the js file at the end of page, and check the dropdown value from javascrpit (here set as variable) and intercept the postback of .NET button:
<script type="text/javascript">
$(document).ready(function () {
var dropdown = 1;
$('.midBtn').click(function () {
if (dropdown == 1) {
mySearch($('.midField').val());
return false;
} else {
// ... postback
}
});
});
</script>
In this case you must be sure that the classes selector (midBtn and midField) are unique.

How to pass codebehind information into javascript function

I have a button in my updatepanel and I'm trying to call a javascript function (after it does it's processing).
I put this code inside the Page_Load:
Dim cstype As Type = Me.GetType()
Dim cs As ClientScriptManager = Page.ClientScript
cs.RegisterStartupScript(cstype, "modalScript", "jsModal('" + msg + "');", True)
keywordSearch.Attributes.Add("onclick", "jsModal('" + msg + "');")
Client Side javascript:
function showModal(msg) {
$("#modal-content, #modal-background, #modal-close").toggleClass("active");
var returnString = msg;
$('#modal-content div').each(function (index) {
$(this).html(returnString);
});
}
How do I pass the values I gather from the server side click event into the javascript function?
I suppose your question is about webform. In this case try this in the aspx
<script type="text/javascript">
$(document).ready(function() {
$("#buttonTest").click(function () {
$("#<%= hiddenField.ClientID%>").val("TEST");
});
});
</script>
<asp:HiddenField runat="server" ID="hiddenField" />
<button id="buttonTest">
Change value hidden field
</button>
<asp:Button runat="server" Text="POST" ID="postButton" />
And this in the CodeBehind
Private Sub postButton_Click(sender As Object, e As EventArgs) Handles postButton.Click
YourLogic(hiddenField.Value)
End Sub

Definition of Function SubmitSurvey have not been found but I defined it

It is literally fifth day I try to solve this.
I try to invoke a method by a button in Razor View, no redirections to other views, just invoke a simple method when button is clicked.
The script looks like:
<script>
function SubmitClick () {
var pid = $(this).data('personid');
var sid = $(this).data('surveyid');
var url = '#Url.Action("SubmitSurvey", "Person")';
$.post(url, { personid: pid, surveyid: sid }, function (data) {
alert('updated');
});
};
</script>
The button looks like:
<button class='mybutton' type='button' data-personid="#Model.Item1.Id" data-surveyid="#survey.Id" onclick="javascript:SubmitClick()">Click Me</button>
The PersonController method looks like:
public void SubmitSurvey(int personId, int surveyId) {
System.Diagnostics.Debug.WriteLine("UPDATING DATABASE");
}
The full view (this is PartialView):
<script>
function SubmitClick () {
var pid = $(this).data('personid');
var sid = $(this).data('surveyid');
var url = '#Url.Action("SubmitSurvey", "Person")';
$.post(url, { personid: pid, surveyid: sid }, function (data) {
alert('updated');
});
};
</script>
#using WebApplication2.Models
#model System.Tuple<Person, List<Survey>>
<hr />
<h1>Surveys</h1>
<input type="button" id="Coll" value="Collapse" onclick="javascript:CollapseDiv()" />
#*<p>
Number of Surveys: #Html.DisplayFor(x => Model.Item2.Count)
</p>*#
#{int i = 1;}
#foreach (var survey in Model.Item2) {
using (Html.BeginForm()) {
<h2>Survey #(i)</h2>
<p />
#Html.EditorFor(x => survey.Questions)
<button class='mybutton' type='button' data-personid="#Model.Item1.Id" data-surveyid="#survey.Id" onclick="javascript:SubmitClick()">Click Me</button>
}
i++;
<hr style="background-color:rgb(126, 126, 126);height: 5px" />
}
<hr />
The problem is that when I click the button:
I get runtime error saying that there is no definition of: "SubmitClick".
I don't see any obvious problems in your code, but given that you're handling this in a sub-optimal way, refactoring your code may solve the problem just by improving the setup.
First, don't embed your scripts directly in the view. I understand that you need to include a URL generated via one of the Razor helpers, but what I'm talking about here is using sections so that your scripts get included in a standard location in the document:
So, in your view:
#section Scripts
{
<script>
// your code here
</script>
}
And then in your layout:
<!-- global scripts like jQuery here -->
#RenderSection("Scripts", required: false)
</body>
This ensures that 1) all your JavaScript goes where it should, right before the closing body tag and 2) all your JavaScript gets run after the various global scripts that it will likely depend on (jQuery).
Second, it's usually a bad idea to define things in the global scope, such as you are doing with your SubmitClick function. If another script comes along and defines it's own SubmitClick function in the global scope, then yours gets hosed or vice versa. Instead, you want to use namespaces or closures.
Namespace
var MyNamespace = MyNamespace || {};
MyNamespace.SubmitClick = function () {
...
}
Closure
(function () {
// your code here
})();
Of course, if you use a closure like this, then you SubmitClick function truly won't exist, as it's no longer in the global scope, which brings me to...
Third, don't use the on* HTML attributes. It's far better to bind functionality to elements dynamically, for example:
(function () {
$('.mybutton').on('click', function () {
var pid = $(this).data('personid');
var sid = $(this).data('surveyid');
var url = '#Url.Action("SubmitSurvey", "Person")';
$.post(url, { personid: pid, surveyid: sid }, function (data) {
alert('updated');
});
});
})();
Now, you've got zero scope pollution and behavior is bound where behavior is defined, instead of tightly-coupling your HTML and JavaScript.

Categories

Resources