I am using a for-loop for displaying data from an API inside a table:
for ($i = 0; $i < count($return['data']); $i++){
echo "<tr><td>".$return['data'][$i]['data_id']."</td>";
echo "<td>".'<button id="delete" class="btn btn-danger" value="'.$return['data'][$i]['data_id'].'" type="text">Delete</button>'."</td></tr>";
}
The result is a table that shows the data_id and the delete button in a row. Now, I want to be able to delete the item by sending the data_id to curl-> delete (API) code when the delete button clicked!
Or run below code on the delete button clicked.
curl --include \
--request DELETE \
--header "<secret key>" \
https://example.com/api/v1/data/{data_Iid}?app_id={appId}
and I need to include the data_id from the loop and pass it to the curt delete code. I used a onClick function to get the value of data_id but it just shows only the first data_id value for each delete button.
How can I achieve my goal and be able to pass the right data_id to curl delete code?
Thanks.
For performance reasons I 'd place an event listener on the table. One JavaScript event listener can catch all clicks on a button. Have a look at the following example.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Button Value Event Listener</title>
</head>
<body>
<table id="my-table">
<thead>
<tr>
<th>Spalte 1</th>
<th>Spalte 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Wert 1</td>
<td>
<button value="1" name="delete[]">Mein Button</button>
</td>
</tr>
<tr>
<td>Wert 2</td>
<td>
<button value="2" name="delete[]">Mein Button</button>
</td>
</tr>
</tbody>
</table>
<script>
var table = document.getElementById('my-table');
table.addEventListener('click', function(event) {
var target = event.target;
if (target.tagName = 'BUTTON' && target.value) {
// remove and place your ajax request here
console.log(target.value);
}
});
</script>
</body>
</html>
With this example you 'll get all values you 've placed in your for-loop for the buttons. Please make sure, that $return['data'][$i]['data_id'] is set and contains the value you expect.
In the geiven example your id is just logged in the console. Please replace the console.log with your asynchronous javascript request (AJAX).
Related
I'm using Power Automate Desktop with an Execute Javascript flow to try to automate some user entry in a Quickbooks Online Payroll form.
When natively using the form, it seems there is an event triggered on blur to validate the numerical input, among other things.
Using the JS flow, updating the input values is not being recognized by the form as once I save it, it shows those inputs as empty.
So I thought I need to trigger the blur event to get the data to save. Here is my JS script:
function ExecuteScript() {
var $payrollTableRows = $("table").first().find("tbody > tr.enabled");
var $regHoursInput;
var decRegHours;
var $bonusInput;
var employeeName;
console.log('Power Automate: Rows Found: ' + $payrollTableRows.length);
$payrollTableRows.each(function(){
employeeName = $(this).find("td:eq(1)").find("a").text();
$regHoursInput = $(this).find("input[wageitemid='HOURLY_PAY']");
if($regHoursInput){
decRegHours = Number($regHoursInput .val());
$bonusInput = $(this).find("input[wageitemid='BONUS']");
$bonusInput.focus();
if($bonusInput){
$bonusInput.val(decRegHours);
$bonusInput.trigger('blur');
}
}
});
}
Here is the script that gets executed on focus and blur on the QB Payroll page.
Why does the script initiated triggers not fire this code?
UPDATE 1:
Adding image of page:
UPDATE 2:
Posting the PAD flow I used. Also got a good overview of this from this video. And how to use Loop and Loop Index from this article.
My Flow:
To do something similar without relying on the JavaScript you could use a variable and loops.
Html used for this flow:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Column A</th>
<th>Column B</th>
<th>Column C</th>
<th>Column D</th>
</tr>
</thead>
<tbody>
<tr>
<td>A <input type="text" id="text-1-input" value="One"></td>
<td>B <input type="text" id="text-2-input" value="Two"></td>
<td>C <input type="text" id="text-3-input" value="Three"></td>
<td>D <input type="text" id="text-4-input" value="Four"onblur="txtOnblur();"></td>
</tr>
<tr>
<td><input type="text" id="text-5-input" ></td>
<td><input type="text" id="text-6-input" ></td>
<td><input type="text" id="text-7-input" ></td>
<td><input type="text" id="text-8-input" hidden></td>
</tr>
</tbody>
</table>
</div>
<script src="https://code.jquery.com/jquery-3.6.1.slim.min.js"></script>
<script>
function txtOnblur(){
$("#text-8-input").show(true);
$("#text-8-input").val('blur triggered!');
}
</script>
</body>
</html>
I used a bit of JavaScript to extract the number of columns and rows in the table, this could have been done with the flow function 'Extract data from web page', but I find the JavaScript a bit faster/easier.
function ExecuteScript() {
var table = document.querySelector('body > div > table');
var colCount = table.children[0].children[0].children.length;
var rowCount = table.children[1].children.length;
return `${colCount} ${rowCount}`
}
Declare one UI element of the first input box. You can reuse this element by replacing/changing the selector properties to use a variable.
In the flow assign the value that will match the HTML selector for the particular control.
and then use the same element wherever you want to change/extract a value (remember the variable now sets the UI element)
The full flow code (copy this and paste it to PAD to see the details)
There will be errors on your side, but you will see the flow.
WebAutomation.LaunchEdge.AttachToEdgeByUrl TabUrl: $'''http://localhost/stackoverAnswer/''' AttachTimeout: 5 BrowserInstance=> Browser
WebAutomation.ExecuteJavascript BrowserInstance: Browser Javascript: $'''function ExecuteScript() {
var table = document.querySelector(\'body > div > table\');
var colCount = table.children[0].children[0].children.length;
var rowCount = table.children[1].children.length;
return `${colCount} ${rowCount}`
}''' Result=> cols_rows
Text.SplitText.Split Text: cols_rows StandardDelimiter: Text.StandardDelimiter.Space DelimiterTimes: 1 Result=> ColsAndRows
Text.ToNumber Text: ColsAndRows[0] Number=> numCols
Text.ToNumber Text: ColsAndRows[1] Number=> numRows
LOOP colIdx FROM 1 TO numCols STEP 1
SET inputBoxVariable TO $'''text-%colIdx%-input'''
WebAutomation.GetDetailsOfElement BrowserInstance: Browser Control: appmask['Web Page \'http://localhost/stackoverAnswer/\'']['Input text \'text-1-input\''] AttributeName: $'''Own Text''' AttributeValue=> inputBoxValue
IF colIdx = 4 THEN
WebAutomation.Focus.Focus BrowserInstance: Browser Control: appmask['Web Page \'http://localhost/stackoverAnswer/\'']['Input text \'text-1-input\''] WaitForPageToLoadTimeout: 60
MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{Tab}''' DelayBetweenKeystrokes: 10 SendTextAsHardwareKeys: False
END
SET inputBoxVariable TO $'''text-%colIdx + 4%-input'''
IF inputBoxValue <> $'''Three''' THEN
WebAutomation.PopulateTextField.PopulateTextFieldUsePhysicalKeyboard BrowserInstance: Browser Control: appmask['Web Page \'http://localhost/stackoverAnswer/\'']['Input text \'text-1-input\''] Text: inputBoxValue Mode: WebAutomation.PopulateTextMode.Replace UnfocusAfterPopulate: False WaitForPageToLoadTimeout: 60
ELSE
WebAutomation.PopulateTextField.PopulateTextFieldUsePhysicalKeyboard BrowserInstance: Browser Control: appmask['Web Page \'http://localhost/stackoverAnswer/\'']['Input text \'text-1-input\''] Text: $'''Skip this one''' Mode: WebAutomation.PopulateTextMode.Replace UnfocusAfterPopulate: False WaitForPageToLoadTimeout: 60
END
END
How it runs:
I don't have QB but I put together a quick html page with a script.
This is the html
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Column 1</th>
</tr>
</thead>
<tbody>
<tr>
<td>Value <input type="text" id="text-1-input" onblur="txtOnblur();">1</td>
</tr>
<tr>
<td>Value <input type="text" id="text-2-input" hidden></td>
</tr>
</tbody>
</table>
</div>
<script src="https://code.jquery.com/jquery-3.6.1.slim.min.js"></script>
<script>
function txtOnblur(){
$("#text-2-input").show(true);
$("#text-2-input").val('blur triggered!');
}
</script>
</body>
</html>
When I run the following script on the page with Power automate it triggers the onblur event on the textbox
function ExecuteScript() {
var $txt = $("input[id='text-1-input']");
$txt[0].onblur();
}
In action:
When I try and call the code in a similar way as you do I only get the list of controls linked to the blur event.
I'm assuming it's jQuery being used in QB. I tend to stick to native JavaScript when it comes to PAD, more typing, but less abstraction.
I want to take req_id but everytime i fetch req_id from table it's gives me undefined in Console.log().Please see in table data req_id and yes the databse connection is okay i can see the value.I tried this both GET and POST method but still i get the same error.All i want is fetch req_id and show it in console.log as defined value
Thank You
<!-- main -->
<section class="pad-70">
<div class="container">
<p id="demo"></p>
<?php
$userQuery = $connection->Show($conobj, "requested_car");
if ($userQuery->num_rows > 0) {
echo "<table><tr><th>Req ID</th><th>Action</th></tr>";
// output data of each row
while ($row = $userQuery->fetch_assoc()) {
echo "<tr ><td id=req_id>";
echo (htmlentities($row['req_id']));
echo ("</td><td>");
echo ('<button onclick="confirmcar()" class="btn btn-lg btn-success">Confirm</button> <button onclick="MyAjaxFunc()" class="btn btn-lg btn-danger">Cancel</button>');
echo ("</td></tr>\n");
}
echo "</table>";
} else {
echo "0 results";
}
$connection->CloseCon($conobj);
?>
</div>
</section>
<!-- main -->
<script>
function confirmcar() {
var req_id = document.getElementById("req_id").value;
console.log(req_id);
}
</script>
So, going from your last edit, I removed the PHP and tried to simulate the HTML that would be generated with several rows.
Now several points remained:
You have missing quotes around your attribute value req_id, as in id="req_id". (Not a real issue as #Quentin pointed out on another answer, but let's keep things tidy for the sake of our eyes)
You're setting event handlers using on... html attributes, which is bad practice. Doing it with js addEventListener will help a lot solving your problem as you'll see below.
One of your problems is that you don't set a different id at each row for your <td>. If your ids are repeated, it probably means you should use a class instead. And setting different ids could have eased the process of selecting the right one on click. But it's not fatal so we'll go from here.
The code snippet below illustrates how you should proceed to get the value which is the inner text of the <td> with id "req_id" on the table row where the "Confirm" button was clicked:
Add an event listener for each of these buttons, and when a button's clicked:
climb up the DOM until you hit its parent <tr>
within this row, find the <td id="req_id"> by its id
read its innerText property
//When the DOM is fully loaded
window.addEventListener('DOMContentLoaded', _e => {
//Find all buttons with class btn-success
const buts = document.querySelectorAll('.btn-success');
//Add a click handler to each one
buts.forEach(button => {
//When the button's clicked
button.addEventListener('click', e => {
//Find parent <tr>
const tr = button.closest('tr');
//Find child with id req_id and get its text
const val = tr.querySelector('#req_id').innerText;
console.log(val);
});
});
});
<section class="pad-70">
<div class="container">
<p id="demo"></p>
<table>
<tr>
<th>Req ID</th><th>Action</th>
</tr>
<tr>
<td id="req_id">My Value 1</td>
<td>
<button class="btn btn-lg btn-success">Confirm</button>
<button class="btn btn-lg btn-danger">Cancel</button>
</td>
</tr>
<tr>
<td id="req_id">My Value 2</td>
<td>
<button class="btn btn-lg btn-success">Confirm</button>
<button class="btn btn-lg btn-danger">Cancel</button>
</td>
</tr>
<tr><td colspan="100">...</td></tr>
</table>
</div>
</section>
I'm using event window.DOMContentLoaded in order for my script to fire only after the DOM has been fully parsed from HTML. Else the buttons would not exist yet when trying to assign event handlers to them.
I have a case where a html file contains multiple elements with the same ID name.
The table row contains 5 columns of which I need to consider 2,3,4,5 columns data.
<tr id='total_row'>
<td>Total</td>
<td>%(count)s</td>
<td>%(Pass)s</td>
<td>%(fail)s</td>
<td>%(error)s</td>
<td> </td>
</tr>
I have the above code at several places in the file. I need to add the respective values using javascript.
An ID is unique in an html page. You can call it THE ID as well wrt a page. You cannot have same ID for two different tags in a single page. But you can use class instead of and ID. Know about it here
So your HTML can be like
<tr class='total_row'>
<td>Total</td>
<td>%(count)s</td>
<td>%(Pass)s</td>
<td>%(fail)s</td>
<td>%(error)s</td>
<td> </td>
</tr>
As an example with jquery you can do something like this,
<!DOCTYPE html>
<html>
<head>
<style>
</style>
</head>
<body>
<table>
<tr class="one">
<td></td>
<td></td>
</tr>
<tr class="one">
<td></td>
<td></td>
</tr>
<tr class="one">
<td></td>
<td></td>
</tr>
</table>
<script src="jquery-1.11.0.min.js"></script>
<script>
$(document).ready(function() {
$(".one").eq(0).find('td').eq(0).html("I'm tracked");
// get 1st tr and get first td
$(".one").eq(1).find('td').eq(1).html("I'm tracked");
// get 2nd tr and get second td
$(".one").eq(2).find('td').eq(0).html("I'm tracked");
// get 3rd tr and get first td
});
</script>
</body>
</html>
But I guess this approach can be tedious.
Id should be unique and if you use the same id, javascript code refers only the first element. but if you still want to use same id than you may try the below code:
$(function(){
$('[id="total_row"]').each(function(){//run for every element having 'total_row' id
var $this = $(this);
$this.find('td').eq(1).text() //to get second column data
$this.find('td').eq(1).text('dummy text') //to set second column data
});
});
You can use XHTML:
<p id="foo" xml:id="bar">
Through XHTML you can apply similar ID to multiple Controls.
Similar questions can be found here:
http://www.c-sharpcorner.com/Forums/
While duplicate IDs are invalid, they are tolerated and can be worked around. They are really only an issue when using document.getElementById.
I'll guess that the table looks like:
<table id="t0">
<tr>
<td>-<th>count<th>Pass<td>Fail<td>Error<td>
<tr>
<td>-<td>1<td>1<td>0<td>0<td>
<tr>
<td>-<td>1<td>1<td>0<td>0<td>
<tr id='total_row'>
<td>Total<td><td><td><td><td>
<tr>
<td>-<td>1<td>1<td>0<td>0<td>
<tr>
<td>-<td>1<td><td>1<td>0<td>
<tr>
<td>-<td>1<td><td>0<td>1<td>
<tr id='total_row'>
<td>Total<td><td><td><td><td>
</table>
<button onclick="calcTotals();">Calc totals</button>
If that's correct, then a function to add each sub–section can be like:
function calcTotals(){
var table = document.getElementById('t0');
var rows = table.rows;
var row, totals = [0,0,0,0];
// For every row in the table (skipping the header row)
for (var i=1, iLen=rows.length; i<iLen; i++) {
row = rows[i];
// If it's a total row, write the totals and
// reset the totals array
if (row.id == 'total_row') {
for (var j=0, jLen=totals.length; j<jLen; j++) {
row.cells[j+1].innerHTML = totals[j];
totals[j] = 0;
}
// Otherwise, add values to the totals
} else {
for (var k=0, kLen=totals.length; k<kLen; k++) {
totals[k] += parseInt(row.cells[k + 1].innerHTML) || 0;
}
}
}
}
In addition to using classes, which works but feels kind of icky to me, one can also use data-* attributes.
<tr class='total_row' data-val-row-type="totals-row">
<td>Total</td>
<td>%(count)s</td>
<td>%(Pass)s</td>
<td>%(fail)s</td>
<td>%(error)s</td>
<td> </td>
</tr>
Then, in your script (jQuery syntax -- querySelectorAll has a similar syntax)
var $totalsRows = $("[data-val-row-type='totals-row']);
When you are in a team with a separate UI designer, this keeps the UI guy from ripping out and changing your class names to fix the new design layout and it makes it quite clear that you are using this value to identify the row, not just style it.
here is my HTML:
...
<table class="tickerTable">
<thead>
<th>Symbol</th>
<th>Accts</th>
</thead>
<tbody ng-repeat="ticker in tickers">
<tr ng-click="showTrades(ticker)">
<td >{{ticker.Ticker}}</td>
<td>{{ticker.TradeCount}}</td>
</tr>
<tr ng-show="currentItem == ticker">
<td colspan="2">{{trades}}</td>
</tr>
</tbody>
</table>
here is the controller:
$scope.showTrades = function(ticker){
$scope.trades = {};
$scope.currentItem = ticker;
$scope.trades = "this is the result of a rest call using the params from $scope.ticker";
};
the table is populated with many rows. for each row i add a blank row that is hidden by default.
when the row is clicked the hidden row displays dynamically generated content that is returned from a rest call made with the params of that particular table row's "ticker" object. the result is injected into $scope.trades and displayed in the now visible TR.
The problem: {{trades}} is being populated in every hidden row along with the revealed row. I only want it to load in the revealed row.
solution
http://plnkr.co/edit/qFZyeuIbt6z5dYEFFHzr?p=preview
In your plnkr you are using ng-if.
There is a bug relatead to ng-if in tables #3104 which will cause problems for you. Maybe you can use ng-show instead as you did in the posted HTML?
Next you may add the trades to the containing ticker. So you display the trades belonging to the current ticker. Then only the selected ticker row will have trades.
<!doctype html>
<html ng-app='portfolio'>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js">
</script>
<script src="script.js"></script>
</head>
<body>
<table ng-controller = "TickerListCtrl">
<thead>
<th>Symbol</th>
</thead>
<tbody ng-repeat="ticker in tickers">
<tr ng-click="showTrades(ticker)">
<td>{{ticker.Ticker}}</td>
</tr>
<tr >
<td ng-show="currentItem == ticker" colspan="2">{{ticker.trades}}</td>
</tr>
</tbody>
</table>
</body>
</html>
$scope.showTrades = function(ticker){
ticker.trades = "this is trades for ticker: " + ticker.Ticker;
$scope.currentItem = ticker;
};
Here is a fork of your plnkr with the described changes.
I am using MVC3, EF Model first on my project.
I have a view with 4 tables and then I have a CustomPickedTable, whenever a user click on a row inside those 4 tables that row moves to CustomPickedTable Table this is the code for it:
<script type="text/javascript">
$(function () {
$('.questionsForSubjectType tbody tr').click(function () {
var origin = $(this).closest('table').attr('id');
$(this)
.appendTo('#CustomPickedTable tbody')
.click({ origin: origin }, function (evt) {
$(this).appendTo('#' + evt.data.origin);
});
});
});
</script>
What I am looking for is some kind of validation that when a user clicks on the submit button there should be a rule that make sures that atleast one row in each of those 4 tables must be moved to CustomPickedTable if not it should not post the form but give the user an errormessage.
This is one of my 4 tables, these get generated by a foreach loop with razor in MVC
<div class="questionsForSubjectType" id="questionsForSubjectType_1">
<table class="box-style2" id="RandomID_c5b9bc7a-2a51-4fe5-bd3a-75b4b3934ade">
<thead>
<tr>
<th>
Kompetens
</th>
</tr>
</thead>
<tbody>
<tr>
<td data-question-id="16">Har konsulten Förmåga att lära sig nytt?</td>
</tr>
</tbody>
<tbody>
<tr>
<td data-question-id="17">Har konsulten rätt kompetens?</td>
</tr>
</tbody>
</table>
</div>
My custom table:
<table id="CustomPickedTable" class="box-style2">
<thead><tr><th>Choosen Questions</th></tr></thead>
<tbody>
</tbody>
</table>
Thanks in advance!
There might be a better way.
But i would add a data-attribute or some class to each of the TD's you can move, and on submit check for each required value.
Created an example here: http://jsfiddle.net/y35Qf/1/
Basicly i added an attribute called data-row, and each table has its own value, on submit i require each of these values to be in the CustomPickedTable - if not i alert that something is missing - else alert success.
You could easily add so you alert which rows are misssing or any other validation you would want.
Is this what you wanted?