Call a code-behind function with ajax? - javascript

Searched a bit, couldn't find a clear answer.
I have a big HTML table with numbers in it.
I have a selector (radiobuttonlist) that the user can click if he wants to see the table in $ or days.
Right now it works perfectly but the page refreshes because i'm calling a code-behind function (RefreshTable) everytime the user clicks on one of the two radiobutton since it changes the format and needs new calculation done by the RefreshTable function
. Is there any ways I can call that function without refreshing the page using ajax or something ?
The function has only one parameter : ProjectID, it's coded in VB.NET and we're using ASP.NET
Here's the table code from the .ASPX page, it's only the shell, everything is added thru a VB.NET method called when the RadioButton is changed (autopostback=true), so we check wich one is selected and execute the VB.NET method to populate the table. (code of the function is below)
note: changed some column\var name since it's sensitive info, but you get the big picture.
<td>
<asp:RadioButtonList RepeatDirection="Horizontal" id="rdiolist" onclick="alert('hello');" runat="server" RepeatLayout="flow" AutoPostBack="true">
<asp:ListItem selected="true"> $ </asp:ListItem>
<asp:ListItem> Days </asp:ListItem>
</asp:RadioButtonList>
</td>
</tr>
</table>
<br />
<table id="tblBudgetRessourceVP" runat="server" class="ProjetTable ProjetTableHover">
<thead>
<tr>
<th style="width:80px">COLUMN 1</th>
<th style="width:120px">COLUMN 2/th>
<th style="width:120px">COLUMN 3</th>
<th style="width:120px">COLUMN 4</th>
<th style="width:120px">COLUMN 5</th>
<th style="width:120px">COLUMN 6</th>
<th style="width:120px">COLUMN 7</th>
<th style="width:120px">COLUMN 8</th>
</tr>
</thead>
</table>
The code behind method, thats what I wanna call without a postback, we want to remove every page refresh. I'll post just a sample of the function since it's pretty repetitive since it does it for every column. I replaced some variables names with random name since it's pretty sensitive data.
Private Sub FillTable(ByVal vProjetID As String)
Dim sqlquery As String = "SELECT SUM(EFFORT_RESRC.NB_JP_PLANF) as Planifie, SUM(EFFORT_RESRC.NB_JP_DDC) as DDC, SUM(EFFORT_RESRC.NB_JP_REEL) as Reel, SUM(EFFORT_RESRC.NB_JP_RESTN) as RAF, " & _
"SUM(EFFORT_RESRC.NB_JP_REVS) as Revise, SUM(EFFORT_RESRC.NB_JP_PROJT) as Projete, SUM(EFFORT_RESRC.ECART_REVS_PROJT) as Ecart,RESRC.ID_VP , VICE_PRESD.DE_VP, TA_COMPS.TAUX " & _
"FROM EFFORT_RESRC INNER JOIN " & _
"TA_COMPS ON EFFORT_RESRC.COMPOSANTEID = TA_COMPS.COMPOSANTEID INNER JOIN " & _
"RESRC ON EFFORT_RESRC.NO_EMPLY = RESRC.NO_EMPLY INNER JOIN " & _
"VICE_PRESD ON RESRC.ID_VP = VICE_PRESD.ID_VP " & _
"WHERE EFFORT_RESRC.PROJETID = '" & vProjetID & "' AND EFFORT_RESRC.ANNEE = '" & dd_ressourceprojet_annee.SelectedValue & "' AND TA_COMPS.ANNEE = '" & dd_ressourceprojet_annee.SelectedValue & "' " & _
"GROUP BY RESRC.ID_VP, VICE_PRESD.DE_VP, TA_COMPS.TAUX " & _
"ORDER BY VICE_PRESD.DE_VP"
Dim dtRessource As New DataTable
Master.GetDataTable(dtRessource, sqlquery)
While (tblBudgetRessourceVP.Rows.Count > 1)
tblBudgetRessourceVP.Rows.RemoveAt(1)
End While
Dim tr As HtmlTableRow
Dim td As HtmlTableCell
For Each ressource As DataRow In dtRessource.Rows
If ressource("DE_VP") <> curStrVP And curStrVP <> String.Empty Then
tr = New HtmlTableRow
td = New HtmlTableCell
td.InnerHtml = curStrVP
tr.Cells.Add(td)
td = New HtmlTableCell
td.Attributes.Add("class", "budget")
If rdiolist.SelectedIndex = 0 Then // Check the selector, if $ or Days display
td.InnerHtml = Format(curPlan, "### ### ### ### ### ##0.00$")
Else
td.InnerHtml = Format(curPlan, "####")
End If
totPlan += curPlan
tr.Cells.Add(td) // Add the cell to the table.
td = New HtmlTableCell
td.Attributes.Add("class", "budget")
If rdiolist.SelectedIndex = 0 Then // Check if JP or $ is selected for display format.
td.InnerHtml = Format(curDDC, "### ### ### ### ### ##0.00$")
Else
td.InnerHtml = Format(curDDC, "####")
End if
totDDC += curDDC
tr.Cells.Add(td)
td = New HtmlTableCell
td.Attributes.Add("class", "budget")
If rdiolist.SelectedIndex = 0 Then // Check if JP or $ is selected for display format.
td.InnerHtml = Format(curRevise, "### ### ### ### ### ##0.00$")
Else
td.InnerHtml = Format(curRevise, "####")
End If
totRevise += curRevise
tr.Cells.Add(td)
Thanks everyone.

Sorry I'm there is a little delay to answer, as I haven't touched VB since so loooong.
Now suppose you have a div (can be a button or any html element) on clicking which you want to bring data from server without making a full postback. Following is the HTML setup.
<div id="click">click</div>
<div id="dvTest"></div>
<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script src="Scripts/json2.js" type="text/javascript"></script>
Following is the jquery code that we will use:
<script type="text/javascript">
$(function () {
$("#click").click(function () {
var o = new Object();
o.ProjectId = 1;
var x = JSON.stringify(o);
$.ajax({
url: 'Default.aspx/GetData',
type: 'POST',
dataType: 'JSON',
contentType: 'application/json;charset=utf-8;',
data: x,
success: function (data) {
data = JSON.parse(data);
var d=data.hasOwnProperty("d") ? data.d : data;
//as we are returning fully rendered table
//we can directly set html of container div
$("#dvTest").html(d);
},
error: function (a, b, c) {
alert(b);
}
});
});
});
</script>
This is what you need to write in your codebehind file (aspx.vb file). This public shared method decorated with WebMethod attribute is called PageMethod. Now as HtmlTable object cannot be automatically serialized we need to use an HtmlWriter to render it to as StringBuilder and return complete HTML to client side:
<WebMethod()>
Public Shared Function GetData(ByVal ProjectId As String) As String
Dim tbl As New HtmlTable
Dim tr As HtmlTableRow
Dim td As HtmlTableCell
'instead of these loops you will polulate table rows/cells
'based on the data returned in your data table
For I As Integer = 1 To 5
tr = New HtmlTableRow
For j As Integer = 1 To 5
td = New HtmlTableCell
td.InnerHtml = "Cell " & I & j
tr.Cells.Add(td)
Next
tbl.Rows.Add(tr)
Next
Dim sb As New StringBuilder
Dim sr As New StringWriter(sb)
Dim hr As New HtmlTextWriter(sr)
tbl.RenderControl(hr)
Return sb.ToString()
End Function
EDIT:- ASP.Net returns JSON objects by serializing .Net objects. But this approach does not works with HtmlTable objects as they do not implement InnerHTML and it throws exception there.

Using AJAX you could create an Generic Handler (assuming you are using VS 2008 or up). A generic handler will have .ashx extension instead of a .aspx extension. Essentially it allows you to control the output whereas a web form .aspx has the UI component and the code-behind. .ashx files are essentially blank with a a reference to your code-behind. In your code-behind you can write the code you need an output what you need for your AJAX response.

Related

Button not firing the third time - ASP.NET code behind C#

I have written a code for button click that should retrieve data from the database and display the data row wise as required. It is working Fine for the first two clicks and it is not firing for the third time... I really don't understand why Please any help.
thank you in advance
The button code
protected void NextButton_Click(object sender, EventArgs e)
{
c++; //integer created to iterate through rows of datatable
qno++; //just counts the rows begining from 1 and displays on page
SqlCommand lque = new SqlCommand("select * from questions where course='" + cour + "' and [group]='" + gr + "' and semester='" + sem + "'", con);
IDataReader rque = lque.ExecuteReader();
if (rque.Read())
{
DataTable dt = new DataTable();
dt.Load(rque);
QuestionNo.Text = Convert.ToString(qno);
Question.Text = dt.Rows[c].Field<string>(4);// only displaying the required columns.
RadioButton1.Text = dt.Rows[c].Field<string>(5);
RadioButton2.Text = dt.Rows[c].Field<string>(6);
RadioButton3.Text = dt.Rows[c].Field<string>(7);
RadioButton4.Text = dt.Rows[c].Field<string>(8);
}
}
source code for the button
<asp:Button ID="NextButton" runat="server" Text="Next" Width="111px" OnClick="NextButton_Click" />
i also checked the data is loaded without any errors into the datatable by passing the datatable as a source to the gridview, it shows all the rows in gridview but in the labels the first 2 rows only displaying. I also chekced the counting varible is only increasing 2 times.enter image description here
a few rows from the table that i am retrieving
Your variables(c for example) will be reset to 0 on every request(button-click). Http is stateless. So you need to persist this value somewhere else(i.e. Session, ViewState, Hiddenfield, etc).
For example with Session, which you should only use if this site has not too much traffic:
private int CurrentRowIndex
{
get
{
if (Session["CurrentRowIndex"] == null)
Session["CurrentRowIndex"] = 0;
return (int)Session["CurrentRowIndex"];
}
set => Session["CurrentRowIndex"] = value;
}
protected void NextButton_Click(object sender, EventArgs e)
{
int currentRowIndex = ++CurrentRowIndex;
// maybe you need this also for your other variables
// ...
}
You should also not read all rows if you only want one, you should modify your sql query. If you use MS SQL-Server you could use ROW_NUMBER function to select only the required row from DB.

Dynamic HTML Elements using data from a Database

I am currently trying to create a website that dynamically displays items when a certain Make, Model, Year is chosen using dropdown lists. The item information was retrieved using web crawling which utilized the HtmlAgilityPack.
So I currently have a database table that is full of thousands of items which contain the columns: id, Make, Model, Year, PartCategory, PartUrl, ImageUrl, PartBrand, PartName, PartPrice.
What I'm attempting to do is separate each site into divs so the user can easily tell which site the item they are looking at is from. Example:
<div id="siteOne">
<table>
<tr>
<td>
<img url="ImageUrl">
PartBrand & PartName & PartPrice
</td>
</tr>
<tr>
<td>
<img url="ImageUrl">
PartBrand & PartName & PartPrice
</td>
</tr>
</table>
</div>
<div id="siteTwo">
.............
</div>
<div id=""siteThree>
.............
</div>
I am currently only using three sites total, and I can easily pull the data into a DataTable and then see how many rows were returned, so that number will be how many dynamic instances I need to create. I'm pretty sure Jquery can handle this job, however I cannot find any examples of people using a DataTable's DataRows to control the dynamic part, usually it is with a button event or something of the sort.
I imagine the code will look something like this:
//this foreach statement will be in the last dropdown list's SelectedIndexChanged event
//when the last dropdown is chosen, a datatable will be returned with all the items that match that particular make/model/year
foreach (DataRow tempRow in tempDataTable)
{
//this should pull data from each column one at a time
//column: 0 = id, 1 = Make, 2 = Model, 3 = Year, don't think I'll need these right now
string partCategory = tempRow[4].ToString();
string partUrl = tempRow[5].ToString();
string imageUrl = tempRow[6].ToString();
string partBrand = tempRow[7].ToString();
string partName = tempRow[8].ToString();
string partPrice = tempRow[9].ToString();
//this is where the jquery would generate the dynamic elements in the table.
//three main divs can be hard coded for now, only using 3 sites currently
//this means the <table></table> in each will most likely be hard coded as well
//the <tr></tr>, <td></td>, <img>, and <a></a> will need to be generated dynamically each loop iteration
}
I've been working on this one step for a while so I figured I would post to see if anyone had any tips or similar examples while I continue to try and solve it myself. Anything would be greatly appreciated. Cheers!
I figured it out, and its quite easy.
heres how my function is setup
protected void drpdwnYear_SelectedIndexChanged(object sender, EventArgs e)
{
//get the data for the specific make/model/year from the database
DataTable dt = new DataTable();
string tempYear = drpdwnYear.SelectedItem.ToString();
string tempManufacturer = Globals.myManufacturer;
string tempModel = Globals.myModel;
Globals.myQuery = "SELECT * FROM CrawlerInfo WHERE Model = '" + tempModel + "' AND Year ='" + tempYear + "'";
try
{
using (SqlConnection con = new SqlConnection(Globals.myConStr))
{
using (SqlCommand cmd = new SqlCommand(Globals.myQuery, con))
{
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
}
catch (Exception ex)
{
handleTheError(ex);
}
//put the data into HTML elements
try
{
int tempflag = 0;
foreach (DataRow tempRow in dt.Rows)
{
string tempCategory = tempRow[4].ToString();
string tempPartUrl = tempRow[5].ToString();
string tempImageUrl = tempRow[6].ToString();
string tempPartBrand = tempRow[7].ToString();
string tempPartName = tempRow[8].ToString();
string tempPrice = tempRow[9].ToString();
string tempStoreName = tempRow[10].ToString();
Image tpImg = new Image();
tpImg.ID = "id_img_" + tempflag;
tpImg.ImageUrl = tempImageUrl;
Page.Controls.Add(tpImg);
HyperLink hyp = new HyperLink();
hyp.ID = "id_link_" + tempflag;
hyp.NavigateUrl = tempPartUrl;
hyp.Text = tempPartBrand + " " + tempPartName + ": " + tempPrice + "\n\n";
Page.Controls.Add(hyp);
tempflag++;
}
}
catch (Exception ex)
{
handleTheError(ex);
}
}
and here hows it displays currently, I just need to figure out how to put them into <div>s so I can style them.

How to automatically call a JavaScript that modify a value before show this value?

I am very new in JavaScript and I have the following problem to solve.
I have a table that contains this td cell:
<td class= "dateToConvert" width = "8.33%">
<%=salDettaglio.getDataCreazione() != null ? salDettaglio.getDataCreazione() : "" %>
</td>
This retrieve a String from an object and show it into the cell
The problem is the retrieved string represent a date having the following horrible form: 20131204 and I have to convert it into the following form: 2013-12-04.
So I am thinking to create a JavaScript that do this work when the value is retrieved.
My problem is: how can I do to automatically call the JavaScript before to show the value into the td cell? (So I show the modified output in the desidered form)
EDIT 1:
So I have create thid JavaScript function into my page:
function convertData() {
var tds = document.querySelectorAll('.dateToConvert');
[].slice.call(tds).forEach(function(td) {
td.innerText = td.innerText.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
});
}
But it don't work because it never enter in this function (I see it using FireBug JavaScript debugger). Why? What am I missing? Maybe have I to call it explicitly in some way in my td cell?
Of course it is better to fix backend method to make it return proper format. But since you have no control over it try to use something like this:
var tds = document.querySelectorAll('.dateToConvert');
[].slice.call(tds).forEach(function(td) {
td.textContent = td.textContent.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
});
Check the demo below.
var tds = document.querySelectorAll('.dateToConvert');
[].slice.call(tds).forEach(function(td) {
td.textContent = td.textContent.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
});
<table>
<tr>
<td class= "dateToConvert" width = "8.33%">
20131204
</td>
<td class= "dateToConvert" width = "8.33%">
20140408
</td>
</tr>
</table>

get dynamic rows data values to prefill the forms using javascript

I have a table in which the rows are dynamic and the values come from database.
for eg my table is as follows:-
name|email
xyz|xyz#gmail.com
pqr|pqr#gmail.com
I have kept the names as link on clicking of which a form opens below with the same field as of table i.e
name:----
email: ----
so now what i want is with opening of the form i also want that the form should get prefilled with values that are there in table ..
for eg:- if a user clicks pqr then a form should get opend with values in it..
name : pqr
email : pqr#gmail.com
I made a javascript function where i pass the userid of the username that the user clicks..and in that i function i did the following :
var id=userid;
var row = document.getElementById(id);
var inputs = row.getElementsByTagName("td");
document.getElementById("fname").value = inputs[0].innerHTML;
document.getElementById("email").value = inputs[1].innerHTML;
and as i am using
inputs[0].innerHTML;
it prints the name like this :
<font size="4">xyz</font>
but I want only 'xyz' in my textbox..for that when I did :
inputs[0].value;
it gave me its value as undefined...why is it so?
please someone guide on getting the form filled with values of the row.
I'm making a few assumptions here. See this fiddle for working code: http://jsfiddle.net/G6Q5X/
Here's a basic table.
<table id="list">
<tr>
<td>Name 1</td>
<td>Email 1</td>
</tr>
<tr>
<td>Name 2</td>
<td>Email 2</td>
</tr>
</table>
First you want to get the table by ID and get the rows that it contains:
//nodeList of all rows in the table
var table = document.getElementById('list').children[0].children;
Then add an event listener to each link:
for(var i=0, len=table.length; i<len; i++){
var link = table[i].children[0].children[0];
link.addEventListener('click', getInfo);
}
The callback for the event listener will call a function, I used one I called "getInfo":
var getInfo = function(){
var name = this.innerHTML;
var email = this.parentNode.parentNode.children[1].innerHTML;
alert('Your name is: ' + name + ' and email is: ' + email)
}
I hope this helps.

Javascript code to get ProductID?

I have a webservice that gets a ProductName and I need the Products that are dropped down from the AutoExtender to be links to each product's individual page.
Right now the URL gets filled with the ProductName, and not the ID:
Default.aspx?id=Test%20Product
needs to be
Default.aspx?id=519
*Note - this site is for internal use only, so we are not worried about getting hacked right now. We want the site to work.
I have been told that what I want to do is not possible by people on the forum for asp.net so I came here hoping for some help. I think it is the javascript that is getting the ProductName from the webservice, and I need it to get the ProductID. I tried rewriting the For Each loop to include ProductID instead of ProductName, but then the AutoCompleteExtender only shows IDs in the results instead of the ProductNames.
Javascript:
<script type="text/javascript">
function AutoCompleteClientMethod(source, eventArgs) {
var value = eventArgs.get_value();
window.location = ("/Product/Default.aspx?id=" + value)
}
</script>
Here is the code for my autoCompleteExtender and the webservice:
<asp:TextBox ID="Search" runat="server" AutoComplete="off"></asp:TextBox>
<asp:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server" TargetControlID="Search" ServicePath="~/ProductSearch.asmx" ServiceMethod="GetProducts" MinimumPrefixLength="1" CompletionSetCount="120" EnableCaching="true" OnClientItemSelected="AutoCompleteClientMethod">
</asp:AutoCompleteExtender>
' To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
<System.Web.Script.Services.ScriptService()> _
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class ProductSearch
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function GetProducts(ByVal prefixText As String, ByVal count As Integer) As String()
Dim ProductSql As String = "Select DISTINCT ProductID, ProductName FROM Product WHERE ProductName LIKE '%" & prefixText & "%' ORDER BY ProductName ASC"
Dim sqlConn As New SqlConnection
sqlConn.Open()
Dim myCommand As New SqlCommand(ProductSql, sqlConn)
Dim myReader As SqlDataReader = myCommand.ExecuteReader()
Dim myTable As New DataTable
myTable.TableName = "ProductSearch"
myTable.Load(myReader)
sqlConn.Close()
Dim items As String() = New String(myTable.Rows.Count - 1) {}
Dim i As Integer = 0
For Each dr As DataRow In myTable.Rows
items.SetValue(dr("ProductName").ToString(), i)
i += 1
Next
Return items
End Function
End Class
Edit: Adding the way the search results used to show up before the switch to the AutoCompleteExtender. I have tried to incorporate this into what I have now, but I can't get anything to work right. Please note that this is the OLD code, what is above is all the code I am using NOW.
<div class="hiddenResults">
<ul id="hiddenResults" style="display:none;">
<asp:ListView ID="lvProducts" runat="server" DataSourceID="dsProducts">
<ItemTemplate>
<li><span class="title"><%# eval("ProductName") %></span></li>
</ItemTemplate>
</asp:ListView>
</ul>
</div>
I tried
<ul style="list-style:none;"><li><a href='/Product/Default.aspx?id=<%# eval("ProductID") %>'>
<asp:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server" TargetControlID="Search" ServicePath="~/ProductSearch.asmx" ServiceMethod="GetProducts" MinimumPrefixLength="1" CompletionSetCount="120" EnableCaching="true" OnClientItemSelected="AutoCompleteClientMethod">
</asp:AutoCompleteExtender></a></li></ul>
but having the autocomplete extender in a list keeps the results of the query from showing.
Edit: Working code:
For Each dr As DataRow In myTable.Rows
Dim id As String = dr("ProductID").ToString()
Dim name As String = dr("ProductName").ToString()
Dim item As String = AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(name, id)
items.SetValue(item, i)
i += 1
Next
See this article, or this one.
In short, create your list items using CreateAutoCompleteItem(). Modify the loop in GetProducts to use CreateAutoCompleteItem():
For Each dr As DataRow In myTable.Rows
dim id as String = dr("ProductId").ToString()
dim name as String = dr("ProductName").ToString()
dim item as String = AutoCompleteExtender.CreateAutoCompleteItem(name, id)
items.SetValue(item, i)
i += 1
Next
That sends both the name and the id to the client. That step is crucial. (If there are syntax errors above, forgive me... It's been a long time since I coded much VB - mostly C# these days.)
Then modify your OnClientItemSelected handler to use get_key() instead of get_value() for the url:
function AutoCompleteClientMethod(source, eventArgs) {
var value = eventArgs.get_key();
window.location = ("/Product/Default.aspx?id=" + value)
}
You need to wrap the href in single quotes, like this:
<a href='/Product/Default.aspx?id=<%# eval("ProductID") %>'>
Now, what are you trying to do with the autocomplete extender? Are you trying to load the results with JavaScript?

Categories

Resources