I'm using Ext.net MessageBox confirm to get confirmation from user,
whenever they want to update a record they click yes on message box. But the message box only show one time when the for loop is done. Here is the code:
foreach (DataRow row in dataTable.Rows)
{
foreach (DataColumn col in dataTable.Columns)
{
var item = row[col];
// some code....
RM.RegisterClientScriptBlock("confirm", "showResult();");
if (hdfIsAgree.Text == "1")
{
hr_TimeSheetCodeServices.Update(item);
}
}
}
Here the client-side code:
<script>
var showResult = function () {
Ext.Msg.confirm('Update', 'Do you want to update?', function (btn) {
if (btn == "yes") {
hdfIsAgree.setValue('1');
} else {
hdfIsAgree.setValue('0');
}
});
}
</script>
<ext:Hidden runat="server" ID="hdfIsAgree" />
First parameter in RegisterClientScriptBlock method is key, which means, that if you invoke this method second time with the same key, your first script will be updated; you will not create two records. Something like this:
for (int i = 0; i < 3; i++)
RM.RegisterClientScriptBlock("confirm", "showResult();");
int count = RM.ClientScriptBlockBag.Count; // 1
will give you only one registered script. Change the key to something unique, to register multiple scripts:
for (int i = 0; i < 3; i++)
RM.RegisterClientScriptBlock($"confirm-{i}", "showResult();");
int count = RM.ClientScriptBlockBag.Count; // 3
Using RM.RegisterClientScriptBlock("confirm", "showResult();"); in for loop will override the previous request with current(latest) request.
Hence this works only for the last value of the for loop, and hence it shows the window only once, as all the previous requests were overridden.
Try running the loop on client side, save the confirmation value in any parameter and then send all values simultaneously(the parameter) on server side with particular id to recognize each value and then apply your logic.
Related
so i have an HTML table with dynamically added rows and ASP.NET text boxes. I have the rows and controls re-instantiated on page_load if the viewstate[dataonpage] = true, and I'm declaring it as true in the method that adds the rows and controls. (I need them to persist on other postbacks)
The problem is that I'm now I've added a CLEAR button that removes all of the html rows (excluding the headers) when it's clicked, and for some reason on button click it gets an index error, or if using Try/Catch it only removes half of the rows (every other row). I believe the problem is something to do with that the viewstate[dataonpage] is still "true", and the data is being re-added on page load. If i add viewstate["dataonpage"] = "false" into the clear button method, the same happens but at least this way on the second click it removes the second half of the rows.
I understand this happens because the button event handler isn't fired until after the page_load which is why it doesn't work on the first click. But what I don't fully understand is why even without this my clear button code doesn't clear all of the rows in the first place.
Any help on understanding why it doesn't work, and a work around will be greatly appreciated!
protected void Page_Load(object sender, EventArgs e)
{
if (Convert.ToString(ViewState["DataOnPage"]) == "true")
{
Getmarketdata();
}
}
protected void Getdatabtn_Click(object sender, EventArgs e)
{
ViewState["DataOnPage"] = "true";
Getmarketdata();
}
Below is method that creates adds table rows and controls:
public void Getmarketdata()
{
String url = "https://api.rightmove.co.uk/api/rent/find?index=0&sortType=1&maxDaysSinceAdded=" + Dayssinceuploadtext.Text + "&locationIdentifier=OUTCODE%5e" + Outcodetext.Text + "&apiApplication=IPAD";
Response.Write(url);
using (var webclient = new WebClient())
{
String Rawjson = webclient.DownloadString(url);
ViewState["VSMarketDataJSONString"] = Rawjson;
dynamic dobj = JsonConvert.DeserializeObject<dynamic>(Rawjson);
int NoOfHouses = dobj["properties"].Count;
Response.Write("<br />" + NoOfHouses);
for (int i = 0; i < NoOfHouses; i++)
{
System.Web.UI.HtmlControls.HtmlTableRow tRow = new System.Web.UI.HtmlControls.HtmlTableRow();
GeneratorTable.Rows.Add(tRow);
String RMlink = String.Format("https://www.rightmove.co.uk/property-to-rent/property-" + dobj["properties"][i]["identifier"].ToString()) + ".html";
HyperLink hypLink = new HyperLink();
hypLink.Text = dobj["properties"][i]["identifier"].ToString();
hypLink.Target = "_blank";
hypLink.NavigateUrl = RMlink;
using (System.Web.UI.HtmlControls.HtmlTableCell tb1 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
tRow.Cells.Add(tb1);
tb1.Controls.Add(hypLink);
}
using (System.Web.UI.HtmlControls.HtmlTableCell tb2 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
TextBox tbEPCe = new TextBox();
tRow.Cells.Add(tb2);
tb2.Controls.Add(tbEPCe);
String txtboxID = (("EPCETxtBox") + i);
tbEPCe.ID = txtboxID;
tbEPCe.Style.Add("background", "none"); tbEPCe.Style.Add("border", "1px solid black"); tbEPCe.Style.Add("border-radius", "2px");
}
using (System.Web.UI.HtmlControls.HtmlTableCell tb3 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
TextBox tbEPCp = new TextBox();
tRow.Cells.Add(tb3);
tb3.Controls.Add(tbEPCp);
String txtboxID = (("EPCPTxtBox") + i);
tbEPCp.ID = txtboxID;
tbEPCp.Style.Add("background", "none"); tbEPCp.Style.Add("border", "1px solid black"); tbEPCp.Style.Add("border-radius", "2px");
}
using (System.Web.UI.HtmlControls.HtmlTableCell tb4 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
TextBox tbBbl = new TextBox();
tRow.Cells.Add(tb4);
tb4.Controls.Add(tbBbl);
String txtboxID = (("BblTxtBox") + i);
tbBbl.ID = txtboxID;
tbBbl.Style.Add("background", "none"); tbBbl.Style.Add("border", "1px solid black"); tbBbl.Style.Add("border-radius", "2px");
}
}
}
}
Below is clear table rows method: (this is the one that isn't working)
public void ClearTableRows()
{
System.Web.UI.HtmlControls.HtmlTable Htmlgeneratortable = ((System.Web.UI.HtmlControls.HtmlTable)GeneratorTable);
int NoOfRows = Htmlgeneratortable.Rows.Count;
for (int j = 1; j < NoOfRows; j++)
{
try
{
Htmlgeneratortable.Rows.RemoveAt(j);
}
catch
{ }
}
}
I'm going to explain what's going on as you have the code written now; I don't have faith in my ability to provide an answer including the exact code changes to be made, so here is what is wrong with your current approach:
Your table, GeneratorTable exists for all clients. That doesn't mean every time someone navigates to your website a table is generated, it means that there is one table, and every client that logs in is getting that one table.
So if you add rows to it for one client, then send the table to another client, both clients will see the same table (with the rows added).
The problem is that emptying out a table is logic that has nothing to do with your back-end server. There's no reason for your server to be handling emptying a table, your server should only handle page navigations and AJAX calls pretty much, it shouldn't be changing how the webpage looks, because the server can only respond to each client one time.
What's the point in responding to a client with GeneratorTable and then updating GeneratorTable on the server? The client will never see the updates made to the table unless they're resent from the server.
You stated that you are new to this and need to learn about JS and client-side, this exercise should serve as an example of why you need to put certain code on the front-end and some code on the back-end, as there isn't really an elegeant way to do what you're looking to do with just the server.
I am trying to pass the index of the clicked button in Repeat(int value) and wrote this -
gp.GetComponentInChildren ().onClick.AddListener(() =>
Repeat(rep));
But when I click any button I got the last index of the button for all.
I want to know is there any way, I can pass the index of that button which i clicked in Repeat()?
void chatDialogs() {
foreach (Transform child in this.transform) {
GameObject.Destroy (child.gameObject);
}
for (int i = 5; i > 0 ; i--) {
int currentStep = Laststep - i;
if (currentStep >= 0) {
gp = (GameObject)Instantiate (playerPreFab);
gp.transform.SetParent (this.transform);
}
gp.GetComponentInChildren<Button> ().onClick.AddListener(() =>
Repeat(**transform.GetSiblingIndex()**));
}
public void Repeat(int speakstep) {
Application.ExternalCall("textspeak", speakstep);
}
in speakstep object of Repeat() the clicked button index should be passed, but its getting the last index in every button I click.
I think you can do something like this:
AddButtonListener(gp.GetComponentInChildren<Button> (), i);
inside your for loop,
when AddButtonListener is defined as:
void AddButtonListener(Button b, int index)
{
b.onClick.AddListener(()=>{Repeat(index)});
}
This way you capture the button index in the listener function (but I'm not sure what the correct name of this pattern is), and I wrote this without actually running it. Hope you have enough info now to get it working.
My test Condition is to Click on a hyperlink in a cell.
--> Table format Tr, Td
Table Columns
Name -- Status -- link
--> 1st we search the row to match the name .
--> After row is found with our search we check the status in the 2nd column, same row.
--> the status changes from processing to Complete.
--> When the Status is Complete a Hyperlink is generated in the 3rd column. Which needs to be clicked.
Upon checking the source code through F12. the Link is generated as a child element of the cell in the 3rd column.
So im trying to find row.cell(2).GetChildren[0];
But as the child element is existing only when the Link is generated, which depends on the application Loading.
i can keep playback.wait(); but that condition is not to be used in my organization until unless its dead end.
Im giving Search properties and waitfor control exist. But that also doesnt work.
Can anyone guide how to wait for the Link which is not existing in the UI currently.
my code looks like below.
HtmlRow row = FindReport(reportName); // Method which finds row
VerifyStatus(reportName, status); // Method verifies status in the row and
returns true if complete
HtmlSpan link = new HtmlSpan(row);
link.SearchProperties.Add(HtmlSpan.PropertyNames.InnerText, "Order",
PropertyExpressionOperator.Contains);
for (int i = 0; i < 60; i++)
{
if (!link.WaitForControlExist())
{
Keyboard.SendKeys(HistoryPage, "{F5}");
}
else
{
Mouse.Click(row.Cells[2].GetChildren()[0]);
return;
}
}
Im stuck here.
Maybe you need to use some kind of custom waitforcontrolexist, with your own steps for researching the control and your own specific timeout.
I'm working on desktop software projects, so not html project, but I guess it should work the same way.
Here is a part of code I use in a more generic function, readapted for your case, if it could help:
HtmlRow row = FindReport(reportName); // Method which finds row
VerifyStatus(reportName, status); // Method verifies status in the row and returns true if complete
HtmlSpan link = new HtmlSpan(row);
int TimoutMilliSecond = 120000//as you told about 2 minutes for the link to be accessible
int count = 1;
bool ControlExist = false;
while (ControlExist == false)
{
link.SearchProperties.Add(HtmlSpan.PropertyNames.InnerText, "Order", PropertyExpressionOperator.Contains);
if (link != null)//null or in your case any bad state you get as result after the SearchProperties on 'link'
{
ControlExist = link.Exists;
}
if (count > TimoutMilliSecond)
{
Assert.Fail("The control 'link' was not found within the timout set out to: " + TimoutMilliSecond.ToString() + " Milliseconds !");
}
Playback.Wait(100);
count = count + 100;
}
if (link != null)
{
link.Find();
}
I have done a bit of searching, and tried several solutions from different posts, but can't seem to get them to work. The basic idea is this... I am customizing an existing usercontrol that lays dynamically generated data out into a single column table of rows. It then has an "edit" link button that does a postback and rebuilds the table with editable fields. I found some jQuery I am using to convert the table into a 2 row table, broken into multiple columns (much easier then trying to re-engineer the data creation/markup within the c#). When the page loads the first time, it works perfectly. However, when I click the "edit" linkbutton, it properly does the postback, but the jQuery doesn't fire. I have tried several configurations to no avail. Here is the jQuery:
private void RegisterScripts()
{
StringBuilder sbScript = new StringBuilder();
sbScript.Append("\tvar tables = $('table[id*=\"tblAttribute\"]');\n");
sbScript.Append("\tfor (var i = 0; i < tables.length; i++) {\n");
sbScript.Append("\t\tvar newTable = document.createElement('table');\n");
sbScript.Append("\t\tvar columns = 2;\n");
sbScript.Append("\t\tfor(var c = 0; c < columns; c++) {\n");
sbScript.Append("\t\t\tnewTable.insertRow(c);\n");
sbScript.Append("\t\t\tfor(var r = 1; r < tables[i].rows.length ; r++) {\n");
sbScript.Append("\t\t\t\tnewTable.rows[c].insertCell(r-1);\n");
sbScript.Append("\t\t\t\tnewTable.rows[c].cells[r-1].innerHTML = tables[i].rows[r].cells[c].innerHTML;\n");
sbScript.Append("\t\t\t\tnewTable.rows[c].cells[r-1].className = tables[i].rows[r].cells[c].className;\n");
sbScript.Append("\t\t\t\ttables[i].rows[r].style.display = 'none';\n");
sbScript.Append("\t\t\t}\n");
sbScript.Append("\t\t}\n");
sbScript.Append("\t\tnewTable.className = tables[i].className;\n");
sbScript.Append("\t\ttables[i].parentNode.appendChild(newTable);\n");
sbScript.Append("\t}\n");
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "RowsToColumnsScript", sbScript.ToString(), true);
}
Here is the call within the Page_Load cycle:
protected void Page_Load(object sender, EventArgs e)
{
RegisterScripts();
// Other Stuff //
}
I have also tried replacing the RegisterClientScriptBlock() with a RegisterStartupScript() and got the same results. What am I missing?
EDIT 2:
Here is the script as it is being added to the client page. I copied right out of the page source (minus my abbreviation):
<script type="text/javascript">
//<![CDATA[
var tables = $('table[id*="tblAttribute"]');
for (var i = 0; i < tables.length; i++) {
var newTable = document.createElement('table');
var columns = 2;
for(var c = 0; c < columns; c++) {
newTable.insertRow(c);
for(var r = 1; r < tables[i].rows.length ; r++) {
newTable.rows[c].insertCell(r-1);
newTable.rows[c].cells[r-1].innerHTML = tables[i].rows[r].cells[c].innerHTML;
newTable.rows[c].cells[r-1].className = tables[i].rows[r].cells[c].className;
tables[i].rows[r].style.display = 'none';
}
}
newTable.className = tables[i].className;
tables[i].parentNode.appendChild(newTable);
}
// Other js registered from other usercontrols
</script>
try wrapping your jquery codes inside the ready function
$(function(){
// place your code here
});
.
<script type="text/javascript">
$(function(){
//<![CDATA[
var tables = $('table[id*="tblAttribute"]');
for (var i = 0; i < tables.length; i++) {
var newTable = document.createElement('table');
var columns = 2;
for(var c = 0; c < columns; c++) {
newTable.insertRow(c);
for(var r = 1; r < tables[i].rows.length ; r++) {
newTable.rows[c].insertCell(r-1);
newTable.rows[c].cells[r-1].innerHTML = tables[i].rows[r].cells[c].innerHTML;
newTable.rows[c].cells[r-1].className = tables[i].rows[r].cells[c].className;
tables[i].rows[r].style.display = 'none';
}
}
newTable.className = tables[i].className;
tables[i].parentNode.appendChild(newTable);
}
// Other js registered from other usercontrols
});
</script>
First off, why don't you do something this...
string script = #"var tables = $('table[id*=\'tblAttribute\']');
for (var i = 0; i < tables.length; i++) {
//rest of your script
";
This will make your script much easier to read and make changes to. White space will be respected. So you don't need the \n and \t characters.
After that, view the resulting HTML in your browser and make sure it made it on there properly. Use your browser's debug tools to execute the script and see if any errors result.
Or just embed the script on the .aspx page instead of adding it from the Code Behind.
Your javascript is expecting your tables to have an id that contains (*=) the string tblAttribute. It would appear that the javascript that creates the newly editable table does not add an id attribute to it. So, while your code-behind registers the script and it executes on each postback, you aren't seeing it because your newly editable table doesn't match the criteria $('table[id*="tblAttribute"]').
You will need to set up an id for the newly created table, but I can't guarantee that this methodology will work (depending on how your usercontrol builds up the various tables you may already have on the screen):
newTable.setAttribute("id", "tblAttribute" + i);
Obviously, id needs to be unique so simply adding your iterator to tblAttribute might create conflicts, but this should get you pointed in the right direction.
EDIT
Seeing your updated comment relating to the UpdatePanel, you might find this answer helpful:
Registering scripts with an UpdatePanel
On one web user control
public void displayFindingSection(int sectionsid,string text,string head)
{
SectionHeading.Text = head;
DataSet totImgs;
totImgs = objGetBaseCase.GetFindingsNewerImages(sectionsid);
FindingViewerlist.DataSource = totImgs;
DataBind();
SectionText.Text = text;
}
On other web user control
public void DisplayFindingsViewer(CipCaseWorkflowItem2 item)
{
FindingViewerDisplay.Visible = true;
ImageAndSimpleViewer.Visible = false;
objGetBaseCase.GetFindingsImages((Convert.ToInt32(Session["CaseId"])), item.ItemId);
FindingsViewerNew = objGetBaseCase.GetFindingViewerNewElementDetails(item.ItemId);
for (int i = 0; i < FindingsViewerNew.Count; i++)
{
FindingViwerDisplay uc = (FindingViwerDisplay)LoadControl("FindingViwerDisplay.ascx");
FindingPlaceholder.Controls.Add(uc);
uc.displayFindingSection(Convert.ToInt32(FindingsViewerNew[i].Index), FindingsViewerNew[i].Text, FindingsViewerNew[i].Title);
}
}
I am adding the all the image in user control and displaying the image, but when i am using the above code, web user control is also adding every time and one image is showing in in control what i want is all images should show in only one user control.. sectionsid is getting the image id from the database. I think prob with for loop but i am unable to solve it.. help me it that
Might be it is happening u have defined it inside the loop
FindingViwerDisplay uc = (FindingViwerDisplay)LoadControl("FindingViwerDisplay.ascx");
FindingPlaceholder.Controls.Add(uc);
On Each loop you are adding uc and calling displayFindingSection whcich ofcouse add 1 image than loop go back add a new control again and than add one image it will go on till your loop completion so add control once before loop and call just displayFindingSection in loop..
Do this,
FindingViwerDisplay uc = (FindingViwerDisplay)LoadControl("FindingViwerDisplay.ascx");
FindingPlaceholder.Controls.Add(uc);
//define here a dataTabel with three columns let say u have datatable dt
for (int i = 0; i < FindingsViewerNew.Count; i++)
{
dt.Rows.Add(Convert.ToInt32(FindingsViewerNew[i].Index), FindingsViewerNew[i].Text, FindingsViewerNew[i].Title);
}
uc.displayFindingSection(dt);
Then work out on that dt in displayFindingSection
Sorry if i am wrong...