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?
Related
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.
I am trying to have autoCompleteExtender to populate on focus of a textbox all possibilities. So far I am having no luck. I have tried adding onfucus in the textbox tag to call a js function that calls the webmethod to populate from a datatable with no luck. The webmethod is being called but nothing shows up on the page. Only after typing something in the textbox does any suggestions turn up.
Here is the aspx page control:
<div title="Model" runat="server" style="text-align:left; padding:20px"><strong>Model</strong>
<asp:TextBox ID="tbModel" runat="server" onfocus="ModelTBOnFocus()"></asp:TextBox>
<div id="ModelListPlacement" style="height:100px; overflow-y:scroll;" ></div>
<ajaxToolkit:AutoCompleteExtender ID="tbModel_AutoCompleteExtender" runat="server" DelimiterCharacters=""
Enabled="True" ServiceMethod="GetListofModels" MinimumPrefixLength="1" EnableCaching="true"
ServicePath="" TargetControlID="tbModel" CompletionInterval="50" CompletionSetCount="40"
CompletionListElementID="ModelListPlacement"></ajaxToolkit:AutoCompleteExtender>
</div>
And Here is the CodeBehind webMethod:
[System.Web.Script.Services.ScriptMethod()]
[System.Web.Services.WebMethod]
public static List<string> GetListofModels(string prefixText)
{
using (SqlConnection sqlconn = new SqlConnection(GetConnectionStringValue("")))
{
sqlconn.Open();
SqlCommand cmd = new SqlCommand("SELECT DISTINCT(Model) FROM Assets WHERE Model like '" + prefixText + "%' " + ModelQuery, sqlconn);
cmd.Parameters.AddWithValue("#Model", prefixText);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
List<string> Models = new List<string>();
TextInfo myTI = CultureInfo.CurrentCulture.TextInfo;
for (int i = 0; i < dt.Rows.Count; i++)
{
string model = myTI.ToTitleCase(dt.Rows[i]["Model"].ToString().ToLower());
Models.Add(model);
}
return Models;
}
}
This is working code. I am just trying to get all possibilities to show up when the textbox is focused. Any help would be much appreciated. Thanks!
EDIT:
This js is working also, but I am not getting any suggestions until something is typed.
Here is the javascript code to call the function:
<script type="text/javascript">
function ModelTBOnFocus() {
PageMethods.GetListofModels("");
}
</script>
Found my answer:
In order to solve this problem I had to set the MinimumPrefixLength="0"
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.
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.
I have a two JavaScript message boxs in an if statement which arent firing - the compiler just bypasses the code as if its not there. This exact same code works elsewhere when its outside the if statement. Can anyone shed some light as to why this isnt working? Thanks
If chk1.Checked And chk4.Checked Then
Dim message As String = "Invalid"
Dim sb As New System.Text.StringBuilder()
sb.Append("<script type = 'text/javascript'>")
sb.Append("window.onload=function(){")
sb.Append("alert('")
sb.Append(message)
sb.Append("')};")
sb.Append("</script>")
ClientScript.RegisterClientScriptBlock(Me.GetType(), "alert", sb.ToString())
Else
If chk2.Checked = True And chk5.Checked = True Then
Dim message2 As String = "Invalid"
Dim sb2 As New System.Text.StringBuilder()
sb2.Append("<script type = 'text/javascript'>")
sb2.Append("window.onload=function(){")
sb2.Append("alert('")
sb2.Append(message2)
sb2.Append("')};")
sb2.Append("</script>")
ClientScript.RegisterClientScriptBlock(Me.GetType(), "alert", sb2.ToString())
Else
Try replacing:
sb2.Append("</script>")
With:
sb2.Append("<\/script>")
in both conditions.
Browser does not allow direct injection, you need to trick it.
I wonder why you are mixing Javascript and VBScript together or how it is gonna run.
Make sure that your onload event isn't setting the checkboxes. The ASP.net lifecycle specifies that the onload event will fire first and therefore set the checkboxes to what is defined in the onload section. If you need to avoid this, just wrap the code that sets the checkboxes in a
if not isPostback then statement to avoid this from happening
aspx:
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
<asp:CheckBox ID="CheckBox1" Text="CheckBox1" runat="server" />
<asp:CheckBox ID="CheckBox2" Text="CheckBox2" runat="server" />
vb:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim message As String = "not (chk1 and chk2)"
If CheckBox1.Checked And CheckBox2.Checked Then
message = "chk1 and chk2"
Else
If CheckBox1.Checked Then
message = "chk1"
ElseIf CheckBox2.Checked Then
message = "chk2"
End If
End If
Dim sb As New System.Text.StringBuilder()
sb.Append("<script type = 'text/javascript'>")
sb.Append("window.onload=function(){")
sb.Append("alert('")
sb.Append(message)
sb.Append("')};")
sb.Append("</script>")
ClientScript.RegisterClientScriptBlock(Me.GetType(), "alert", sb.ToString())
End Sub
i tested this code ....
try == rather than = in if condition!