Passing JS parameter to c# function in code behind- .net - javascript

I am trying to call a c# function from JavaScript but the problem is, I need to pass a JS parameter for the function. How can I do this?
Here's my Js
var categoryLists = <%= this.javaSerial.Serialize(this.categoryList) %>;
function addInput(type, value, name, id, onclick, parentId) {
var element = document.createElement("input");
element.type = type;
element.value = value;
element.name = name;
element.id = id;
element.onclick = onclick;
element.src = "trash.png";
element.style.width = "25px";
element.style.height = "25px";
element.style.marginBottom = "3%";
var parent = document.getElementById(parentId);
parent.appendChild(element);
}
function addBreak(parentId) {
var br = document.createElement("br");
var parent = document.getElementById(parentId);
parent.appendChild(br);
}
window.onload = function () {
alert(this.categoryLists.length);
for (var j = 0; j < this.categoryLists.length; j++) {
var temp = "button" + j;
addInput('image', '', temp, temp, <%=DeleteCategory(%>+categoryLists[j]), 'rightdiv');
addBreak('rightdiv');
}
}
categoryLists[j] is my paramter
Here's the c# code
public void DeleteCategory(string category){
}
public JavaScriptSerializer javaSerial = new JavaScriptSerializer();
Update- I call c# functions this way... <%= function()%> and they work fine.
Thank you in advance
Update- with all the comments, I have tried using ajax or jquery - i am not sure what this is ... now my js looks like this and its broken... are there syntax issues?
$(function () {
function addInput(type, value, name, id, onclick, parentId) {
var element = document.createElement("input");
element.type = type;
element.value = value;
element.name = name;
element.id = id;
element.onclick = onclick;
element.src = "trash.png";
element.style.width = "25px";
element.style.height = "28px";
element.style.marginBottom = "3%";
var parent = document.getElementById(parentId);
parent.appendChild(element);
}
function addBreak(parentId) {
var br = document.createElement("br");
var parent = document.getElementById(parentId);
parent.appendChild(br);
}
for (var j = 0; j < this.categoryLists.length; j++) {
var temp = "button" + j;
addInput('image', '', temp, temp, temp, 'rightdiv');
addBreak('rightdiv');
}
});

You have quite a few ways to do this.
You can use the cheater approach. Drop in a text box, and a standard button (that will call server side code behind). (set clientID mode for this button and text box as static).
<asp:Button ID="btnHidden" runat="server" Text="hidden but" />
<asp:TextBox ID="TextHiddenBox" runat="server" ClientIDMode="Static" ></asp:TextBox>
Ok, now in your js you can go:
<script>
// set the value we want to pass in the hidden text box
$('#txtHidden').value("abc");
$('#hiddenButton').click;
<script>
Note: above is jQuery syntax.
You could do this: (pure js no jQuery)
var myvaluetopass = "this is some text to pass as variable";
document.getElementById('<%= TextHiddenBox.ClientID %>').value = myvaluetopass;
document.getElementById('<%= btnHidden.ClientID %>').click();
so you don't have to introduce jQuery here - it can be some "time" and "hassle" to setup + get jQuery working.
So, the above will simple click on the hidden button, and the hidden text box will have the value that the code behind can work with. Once you wire up the above?
Then hide the button and the text box like this:
<asp:Button ID="btnHidden" runat="server" Text="hidden but" style="display:none"/>
<asp:TextBox ID="TextHiddenBox" runat="server" ClientIDMode="Static" style="display:none" ></asp:TextBox>
Now, the above is certainly somewhat "klugey". But when you starting out, it can work quite well. So, you set the value of some text box (often hidden), and then with js you FIRE the click event of another button (again often hidden). This now gets you a easy way to run one particular code behind routine, and not have to wire up complex ajax code.
The next approach? Well, fire a post back command. This again like the above hidden button trick assumes you need/want a post back here in addition to calling that one routine. this approach is somewhat better in that you don't have to drop on the form two hidden controls.
You ALSO need to drop in the script manager for this to work (don't know why). But you can do this in your code:
var myvaluetopass = "this is some text to pass as variable";
__doPostBack("MyCoolEventName", myvaluetopass);
So, the above fires a page post back, and then in the load event, we have this:
If Request("__EVENTTARGET") = "MyCoolEventName" Then
Dim str As String = Request("__EVENTARGUMENT")
Debug.Print("passed value = " & str)
End If
or as C#
if (Request("__EVENTTARGET") == "MyCoolEventName")
{
string str = Request("__EVENTARGUMENT");
Debug.Print("passed value = " + str);
}
So the above are some simple ways.
The ALL above ideas do cause a full page post-back to run. Now, if the routine you calling DOES need to set/get/change/deal with/see any control on the page, then of course one does need and want that all important page post back.
Last but not least? Well, you can do a ajax call, and that will call a specific routine on your page, pass values (if you want), and ONLY run that one routine. This can be VERY nice, it fast, and you do NOT get a full page post back. So, if the routine you need to run does not have to modify, or do much of anything on the web page, then ajax is certainly the best way to go (assuming that the routine you calling does NOT need to modify or change things on the page - since as noted, no page post-back will occur. And if you looking to use that value with code behind and modify things on the page, then you will need a post-back.
But, lets assume you do need to pass one, or do values.
Well, I suggest jQuery - it just makes the code a bit easier to write.
So, say in your web page, you have this simple sub, and want to pass two values:
<WebMethod()>
Public Shared Sub MySimpleSub(MyCoolPassValue As String, Age As Integer)
Debug.Print("passed string value = " & MyCoolPassValue & vbCrLf & "Age = " & Age.ToString)
End Sub
or:
[WebMethod()]
public static void MySimpleSub(string MyCoolPassValue, int Age)
{
Debug.Print("passed string value = " + MyCoolPassValue + Constants.vbCrLf + "Age = " + Age.ToString());
}
So in above, it just a public sub. (in the code behind for that web page).
(note the Shared - it HAS to be Static sub - since we calling the page - but don't have the full class object model).
We also need a
Imports System.Web.Services
Ok, now to call the above as ajax?
We get this:
var myvaluetopass = "this is some text to pass as variable";
var age = 23;
$.ajax({
type: "POST",
async: true,
url: 'OnePicture.aspx/MySimpleSub',
data: JSON.stringify({MyCoolPassValue: myvaluetopass, Age: age}),
contentType: "application/json; charset=utf-8",
datatype: "json"
}
);
}
So in above, we passed two values to the sub in the web form.
The above did assume jQuery. I can write it out as pure JavaScript, but the above thus gives;
How to pass values - hidden control idea.
Or use __dopostback - this gets rid of the requirement to have a button + hidden text box
(and use style="display:none" to hide the button and text box above (if you using that idea, and get it working).
As noted, I don't know why, but you have to drop a Scriptmanager into the page if you going to use dopostback. (or pass a valid control ref as the first parameter - it will just to your button code behind routine). But, my dopostback example simple gets/grabs the value in teh page load event (event args).
And then last but not least, we pass a value direction to a web method (sub) in that page - this is a ajax call, and just keep VERY much in mind that the code for this routine has to work without assuming that a page post-back occurred (compared to all previous examples that assumed you need a post back).

Related

How to give a "checkbox onChange event" the calling Input Id (in Xpages)

I have an Xpages Application and I am currently using a checkbox in a repeat control to call an onChange function, I want to parse the calling element/elementID to my Client Side Javascript located in: Events->onChange. My problem is that my Javascript returns undefined when using "this". I tried to parse an object on the Function call but that doesnt seem to be possible in Xpages either.
Javascript Code (probably wont be much help):
var fieldsets = document.querySelectorAll("table.checkboxGroups");
console.log(fieldsets);
console.log("-----------------");
var fieldsetCurrent = fieldsets[0]; //this is where I need the calling elem
console.log(fieldsetCurrent);
console.log("-----------------");
var fieldsetCheckboxes = fieldsetCurrent.getElementsByTagName("input");
console.log(fieldsetCheckboxes);
console.log("-----------------");
for(i=0;fieldsetCheckboxes.length;i++){
var elem = fieldsetCheckboxes[i];
console.log(i + " : " +elem);
elem.setAttribute("checked","");
//elem.checked;
}
If your repeating on notes documents then you could add the documentid to the checkbox as an attribute and use this id to call your onChange eventhandler. dojo.query might also be of some value here.

Custom ASP.Net Server Controls: How to call javascript function in parent page

I have built a number of custom server controls and routinely call javascript functions that are embedded into my controls. But I haven't been able to figure out how to create a property that the user of the control can add their own function to and their javascript function in the page containing the control will be called. I need to do something like OnClientClick for an asp:Button control.
Edit 1:
Thanks to the answer by #h2015 I have made progress on this.
In my control I create a public property for the user's script,
public string EditAddressScript
{
set
{
string scriptName = "EditAddressScript";
Type csType = this.GetType();
ClientScriptManager csm = Page.ClientScript;
string scriptText = string.Format("function EditAddress() {{{0}}}", value);
csm.RegisterClientScriptBlock(csType, scriptName, scriptText, true);
}
}
Then in the RenderContents section of my control I check whether a value has been specified for EditAddressScript and create a button if it has.
output.Write("<input id='btnEdit' type='button' value='Edit Address' style='font-size: 6pt;' onclick='EditAddress();' />");
The page that uses this control creates it dynamically so I do something like this,
ECFControls.DefendantAddressReview defendantAddress = new ECFControls.DefendantAddressReview();
divControls.Controls.Add(defendantAddress);
defendantAddress.ClientEditAddressScript = "alert('Hello, World');";
This works, but is far from optimal.
I would like to define the script in the aspx page and then just give my control the name of the script, rather than setting the value of EditAddressScript to the actual javascript code.
In the RenderContents section of the control I have the name of the script hardcoded I would like that to be dynamic.
Edit 2:
Okay, it looks like I was making this far more complicated than necessary. All that is needed is to create a script in the parent aspx page and set the event in the control to that script.
So this is what I have now
Add script to aspx page.
function EditAddress() {
alert("Hello, World");
}
Create a property in the control to hold the value (_EditAddressScript is a private string variable in the control)
public string EditAddressScript
{
set
{
_EditAddressScript = value;
}
}
Then in the RenderContents section of the control I check whether a value has been specified for EditAddressScript and create a button if it has.
if(_EditAddressScript.Trim() != "")
output.Write(string.Format("<input id='btnEdit' type='button' value='Edit' style='font-size: 6pt;' onclick='{0}' />", _EditAddressScript));
Create the control like this,
ECFControls.DefendantAddressReview defendantAddress = new ECFControls.DefendantAddressReview();
divControls.Controls.Add(defendantAddress);
defendantAddress.EditAddressScript = "EditAddress()";
If the control were created declaratively I could do this,
<ECF:DefendantAddressReview ID="defendantAddressReview" runat="server" EditAddressScript="EditAddress()" />
Is there a better approach?
Thanks.
this.Page.ClientScript.Register...
https://msdn.microsoft.com/en-us/library/ms178207.aspx
I explored two possible solutions in the edits to my original question. The second edit achieves the desired result. I wanted to have an optional property for a custom ASP.Net server control that would specify the name of a javascript function that the user of the control could place in the same page as the control. Here's how I did it.
Add a public string property to the server control that defines the name of your javascript function. (_CustomJavascript is a private string variable in the control)
public string CustomJavascript
{
set
{
_CustomJavascript = value;
}
}
Then in the RenderContents section of the control check whether a value has been specified for _CustomJavascript and add the code to call that javascript if it has been. In my case I was creating a composite control and wanted an edit button to display that would call the user's javascript function.
if(_CustomJavascript.Trim() != "")
output.Write(string.Format("<input id='btnEdit' type='button' value='Edit' style='font-size: 6pt;' onclick='{0}' />", _CustomJavascript));
All the user has to do is write their function.
function EditAddress() {
alert("Hello, World");
}
And give the name of their function to the CustomJavascript property when declaring the control.
<cc:AddressReview ID="addressReview" runat="server" CustomJavascript="EditAddress()" />

How to Pass/access value from javascript to C# page load

I have tried below approach.
I used one hidden field on aspx page named hdnTime.
Then I assigned value to hidden field in javascript function.
<script type='text/javascript'>
function getLocalTimeZone() {
document.getElementById('ctl00_bcr_hdnTime').value = 10;
var hidden = document.getElementById('ctl00_bcr_hdnTime');
var timezone = String(new Date());
hidden.value = timezone.substring(timezone.lastIndexOf('(') + 1).replace(')', '').trim();
}
Then on C# page load I tried below code.
ScriptManager.RegisterStartupScript(Page, GetType(), "disp_confirm", "getLocalTimeZone()", true);
string test = hdnTime.Value;
But I am getting blank value for hdnTime.
Please let me know if I missing something here.
Page_Load event is executed before document.ready so anything set in document.ready won't be available in Page_Load event
You can set value on click of a button than in c# you can get that value.

VB.NET Gecko Web Browser javascript function calling?

I am using GeckoWebBrowser within my VB.NET (Windows Form App) program. The GeckoWebBrowser loads a local html file. This html has embed in-line a svg file (human body diagram with bones and internal organs) with a javascript function for picking up all the "ids" of the elements from the svg document. I'd like to call the aforementioned javascript function from VB.NET (Windows form app), but I don't know how to do so. Can anyone help me, or give me a source code example please? All the stuff I've found is based in C#...
This is my javascript function in my html file:
<script type="text/javascript">
(funcion () {
// Function to be called in VB.NET when the DOM is loaded
var SVGHandler = function () {
// Picking up the id Root Node="CUERPO_HUMANO" into svg variable
var svg = document.querySelector('#CUERPO_HUMANO');
// In Items we save all the <g> which have an ID
var items = svg.querySelectorAll('g[id], path[id]');
//var items = svg.querySelectorAll('g[id]');
// We loop all the nodes saved in Items and add them to click event listener
forEach(items, function (index, value) {
value.addEventListener('click', function (event) {
event.preventDefault();
//We avoid the spread of events
event.stopPropagation();
return event.currentTarget.id
// console.log(event.currentTarget.id)
});
});
}
// https://toddmotto.com/ditch-the-array-foreach-call-nodelist-hack/
var forEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]); // passes back stuff we need
}
};
// With this method, we call a SVGHandler when DOM is totally loaded
document.addEventListener('DOMContentLoaded', SVGHandler);
})();
</script>
What code should I use in VB.NET for calling my javascript function each time I click on a specific bone or organ in the human body diagram loaded in GeckoWebBrowser?
I want to save the "id" picked up with the calling into a string variable in order to use it as a parameter in a SQL statement and populate a DataGridView.
I've been searching and all that I could find was related to C#, not a single VB.NET example. Even though I was trying to figure out the equivalence in VB.NET trying to convert the C#'s examples to VB.NET, I have some doubts on how to do the javascript call. According to my javascript function It could be something like this:
browserControl.Navigate("javascript:void(funcion())");
Please, Can anyone help me to solve this? I would be very thankful...
Well since you have set click EventListener's I think that you're not looking for a way to call the eventual function from VB.NET but this is quite unclear according to your post so I'll give you examples on how to call a javascript function and how to trigger a reaction in your VB.NET code through javascript using GeckoWebBrowser.
Your code snippet of your attempt to call a js function from your vb code is correct. The only problem is that you haven't defined any callable js function in your html file. In your case you should do this to trigger your main js function from vb:
//Sorry I don't know vb. I'll give example in c# keeping it as simple as possible so that you can easily convert it to vb
Gecko.GeckoHtmlElement humanBodyPart = (Gecko.GeckoHtmlElement) browserControl.Document.GetElementById("your id");
humanBodyPart.Click();
The above code finds the element with the matching id in the GeckoWebBrowser and clicks it. Since you've set click EventListener's, by clicking one of the elements this will trigger the function assigned to them to run.
Moving on, in order to save the id of the elements to a string variable in your vb code you'll need to add this little bit of js code in to the code that you pass as 'callback' parameter in your forEach function:
var event = document.createEvent('MessageEvent');
var origin = window.location.protocol + '//' + window.location.host;
var event = new MessageEvent('jsCall', { 'view': window, 'bubbles': false, 'cancelable': false, 'data': 'YOUR EVENTUAL ID AS A STRING (THIS STUFF GOES BACK TO THE VB/C# CODE)' });
document.dispatchEvent (event);
Then the above snippet should be handled in your vb code like this:
browserControl.AddMessageEventListener("jsCall", (id) =>
{
//Here in the variable id you have your clicked id as a string. Do what you wanted to do...
});
VB side :
you need wait until the document is completed to add listeners
for example : _DocumentCompleted
Private Sub GeckoWebBrowser1_DocumentCompleted(sender As Object, e As Gecko.Events.GeckoDocumentCompletedEventArgs) Handles GeckoWebBrowser1.DocumentCompleted
GeckoWebBrowser1.AddMessageEventListener("my_function_name JS_side", AddressOf my_sub_for_treatment)
End Sub
JS side :
var event = document.createEvent('MessageEvent');
var origin = window.location.protocol + '//' + window.location.host;
var event = new MessageEvent('my_function_name JS_side', { 'view': window, 'bubbles': false, 'cancelable': false, 'data': my_data_to transfer });
document.dispatchEvent (event);

Trying to clean out form inputs with jQuery so I can add it back into the form

I have a pretty simple HTML form where users can enter in information about a person. Below that form is a button which allows them to 'add more'. When clicked, the 'person' form is copied and appended to the page.
The way I used to do this was to take my HTML file, copy out the relevant section (the part that gets 'added more') and then save it into a variable in the Javascript. This became rather annoying when I had to make changes to the form as I would then have to make the same changes to the Javascript variable.
My new method is to create the variable dynamically in Javascript. When the page loads, I use jQuery to grab out the 'add more' part of the code and cache the HTML into a variable. Then when the 'add more' button is clicked, I append that cached HTML to the page.
The problem is with form inputs. The server-side code autofills the form with the user's data from the database. I want to cache that HTML data with no form inputs...
My current function looks like this:
function getHTML($obj, clean)
{
if (clean)
{
var $html = $obj.clone();
$html.find('input').each(function() { $(this)[0].value = ''; });
}
else
{
var $html = $obj;
}
var html = $html.wrap('<div></div>').parent()[0].innerHTML;
$html.unwrap();
return html;
}
It doesn't work. I'm also unsure if this is the best approach to solving the problem.
Any ideas?
I don't know why this wouldn't work. I can't see how the function is being called, or what is being passed to it.
I guess one thing I'd do differently would be to create a .clone() whether or not you're "cleaning" the inputs. Then you're not wrapping and unwrapping an element that is in the DOM. Just use the if() statement to decide whether or not to clean it.
Something like this:
function getHTML($obj, clean) {
var $clone = $obj.clone();
if (clean) {
$clone.find('input').each(function() { this.value = ''; });
}
return $clone.wrap('<div></div>').parent()[0].innerHTML;
}
Or a little more jQuery and less code:
function getHTML($obj) {
return $obj.clone().find('input').val('').end().wrap('<div/>').parent().html();
}
A little less efficient, but if it only runs once at the page load, then perhaps not a concern.
Or if it is going to be made into a jQuery object eventually anyway, why not just return that?
function getHTML($obj) {
return $obj.clone().find('input').val('').end();
}
Now you've returned a cleaned clone of the original that is ready to be inserted whenever you want.
EDIT:
Can't figure out right now why we can't get a new string.
Here's a function that will return the DOM elements. Beyond that, I'm stumped!
function getHTML($obj, clean) {
var $clone = $obj.clone();
if (clean) {
$clone.find('input').each(function() {
this.value = '';
});
}
return $clone.get(); // Return Array of DOM Elements
}
EDIT: Works now.
I ditched most of the jQuery, and used .setAttribute("value","") instead of this.value.
Give it a try:
function getHTML($obj, clean) {
var clone = $obj[0].cloneNode(true);
var inputs = clone.getElementsByTagName('input');
console.log(inputs);
for(var i = 0, len = inputs.length; i < len; i++) {
inputs[i].setAttribute('value','');
}
return $('<div></div>').append(clone)[0].innerHTML;
}
I would wrap the part of the form that needs to be cloned in a <fieldset>:
<form id="my_form">
<fieldset id="clone_1">
<input name="field_1_1">
<input name="field_2_1">
<input name="field_3_1">
</fieldset>
</form>
Add one more
Then for the jQuery script:
$("#fieldset_clone").click(function(event) {
// Get the number of current clones and set the new count ...
var cloneCount = parseInt($("fieldset[id^=clone_]").size());
var newCloneCount = cloneCount++;
// ... then create new clone based on the first fieldset ...
var newClone = $("#clone_1").clone();
// .. and do the cleanup, make sure it has
// unique IDs and name for server-side parsing
newClone.attr('id', 'clone_' + newCloneCount);
newClone.find("input[id^=clone_]").each(function() {
$(this).val('').attr('name', ($(this).attr('name').substr(0,7)) + newCloneCount);
});
// .. and finally insert it after the last fieldset
newClone.insertAfter("#clone_" + cloneCount);
event.preventDefault();
});
This would not only clone and clean the set of input fields, but it would also set new ID's and names so once the form is posted, their values would not be overwritten by the last set.
Also, in case you want to add the option of removing sets as well (one might add too many by mistake, or whatever other reason), having them wrapped in a <fieldset> that has an unique ID will help in accessing it and doing a .remove() on it.
Hope this helps.

Categories