Angular primeNg pEditableColumn dropdown onChange event - java

I have a p-table with p-editable column which is a dropdown as follows:
<ng-template pTemplate="body" let-rowData let-columns="columns" let-editing="editing">
<tr style="font-size:10px;" [pEditableRow]="rowData" >
<ng-container *ngFor="let col of columns" [ngSwitch]="col.field">
<td *ngSwitchCase="'dob'" [colSpan] = "1">
{{rowData[col.field] | date: 'dd-MMM-yyyy hh:mm'}}
</td>
<td *ngSwitchCase="'updated'" [colSpan] = "1">
{{rowData[col.field] | date: 'dd-MMM-yyyy hh:mm'}}
</td>
<td *ngSwitchCase="'assignedTo'" [colSpan] = "1" pEditableColumn>
<p-cellEditor>
<ng-template pTemplate="input">
<p-dropdown [options]="assigneList" [(ngModel)]="rowData[col.field]" (onChange)="changeAssigne($event)" ></p-dropdown>
</ng-template>
<ng-template pTemplate="output">
{{rowData[col.field]}}
</ng-template>
</p-cellEditor>
</td>
<td *ngSwitchDefault [colSpan] = "1">
{{rowData[col.field]}}
</td>
</ng-container>
</tr>
</ng-template>
As per primeNg documentation assigneList has a label, value in addition i have an id field that is unique for each row.
My dropdown works perfectly fine foreach row and corresponding element gets selected perfectly. However I have a requirement where onChange of dropDown i have to update the DB.
My onChange function which is changeAssigne(event), currently displays only value. I want the onChange to give me the entire object.
Component.ts code
...///
assigneList : BoardAssigneDTO[] =[];
this.assigneList = this.data.assigneList;
///..
and model is as follows:
export class BoardAssigneDTO {
id : Number = 0;
label : string = '';
value : string = '';
}
So in this case my onChange should have object in the form BoardAssigneDTO which has id, label, value. How can this be done.
Initially i was trying to pass just object as id, Name, Country but dropdown wouldnt work. So followed as per documentation primeNG table edit with dropdown and created label and value pair which is concat of name and country. But my unique key is id and I want to pass this id to the backend. How is this possible. Any suggestions highly appreciated.

This doesn't work as it is for normal dropdowns if it is inside a p-table.
By default p-dropdown value is mapped to value property in option list object.
I have used the below approach to fix achieved this long time back.
Add the event and pass the value and list:
<p-dropdown [options]="assigneList" [(ngModel)]="rowData[col.field]" (onChange)="changeAssigne(assigneList,rowData[col.field])" ></p-dropdown>
Find the object and assign to model in changeAssigne method
changeAssigne(list,value){
// find out the object from list
let selectedItem = list.filter((item)=>{
return item.value === value;
});
console.log(selectedItem);// selected option object
}

Related

Unable to grab an element in a dynamic table where we have only text of a td tag

I have a table whose data changes according to what is added and deleted. In the table there are multiple columns Name, Qty, type, Status. All i have is the Name Text with me , i need to find the status field of that row which has that Name.
Problem is the html tags of have same class names and i tried grabbing the parent and sibling everything failed. Please find the html structure of the table below:
<table>
<thead> </thead>
<tbody>
<tr>
<td class = "c1">
<a class = txtclass> text1 </a>
</td>
<td class = "c1"> Qty </td>
<td class = "c2"> type </td>
<td class = "c3">
<div id = "1" class = "status1"> /div>
</td>
</tr>
<tr>
<td class = "c1">
<a> text2 </a>
</td>
<td class = "c1"> Qty </td>
<td class = "c2"> type </td>
<td class = "c3">
<div id = "2" class = "status2"> /div>
</td>
</tr>
</tbody>
</table>
So all i have with me is text2 and i need to get the with the status of that row.
How do i proceed. I tried
List<WebElement> ele = driver.findElements(By.xpath("//*[#class = 'txtClass'][contains(text(),'text')]"));
for(WebElement el1:ele)
{
WebElement parent = el1.findElement(By.xpath(".."));
WebElement child1= parent.findElement(By.xpath("//td[4]/div"));
System.out.println(child1.getAttribute("class"));
}
this gives me the class name of the status of the first row in the table always.
Same i tried with
WebElement child = el1.findElement(By.xpath("//following-sibling::td[4]/div[1]"));
i got the same thing class name of the first row in the table. I figured since the class name of the are same for all child elements it will always grab the first row elements, and not the one from the row.
Please help i am stuck here for long, let me know if you need any other details.
You are trying using -
el1.findElements(By.xpath("//following-sibling::td[4]/div[1]"));
It is matching all the element present with format td[4]/div[1] in your page and retrieving first match.
You have to use following xpath to grab status present under div based on you text.
driver.findElement(By.xpath(".//tr/td[contains(.,'text1')]/following-sibling::td[3]/div")).getAttribute("class");
If your requirement to extract all status try following code-
List<WebElement> allElements = driver.findElements(By.xpath(".//tr/td[contains(.,'text2')]/following-sibling::td[3]/div"));
for(WebElement element:allElements)
{
String status = element.getAttribute("class");
System.out.println(status);
}
I think this approach suitable for you:
Get all div elements containt attribute status :
List<WebElement> listChildStatus = driver.findElements(By.xpath(".//tr[.//a[contains(.,'text')]]//div"));
Get specific div elements containt attribute status :
WebElement childStatus = driver.findElement(By.xpath(".//tr[.//a[contains(.,'{TEXT}')]]//div"));
{TEXT} = the text value that you have
You need to locate the element with the text, go one level up, and then get the sibling with the status
WebElement statusElement = driver.findElement(By.xpath(".//td[a[contains(text(),'text2')]]/following-sibling::td[3]/div"));
String status = statusElement.getAttribute("class"); // will be status2
If you don't want to relay on index you can use last() to find the last sibling
WebElement statusElement = driver.findElement(By.xpath(".//td[a[contains(text(),'text2')]]/following-sibling::td[last()]/div"));

Trouble locating element

I'm testing an application and in the application there is a table containing checkboxes (3 rows, x columns). Below is the html for part of this table (1row). I'm trying to click on the text of one of these items to either select or deselect a checkbox based on the text. So for example, I want to click on the text 'Text next to checkbox for nr 8' in order to select that textbox. However, I don't want to go there via a hard xpath using code like /table/tbody/tr[2]/td[2]/div/span)[2] but based on the text. I'm trying code like the ones below but they don't seem to work:
driver.findElement(By.xpath("(//*[#class='settingsPanelTD' and text()='Text next to checkbox for nr 8']")).click();
driver.findElement(By.xpath("(//*[#class='settingswidgetTitle' and text()='Text next to checkbox for nr 8']")).click();
driver.findElement(By.xpath("(//*[#class='settingswidgets' and text()='Text next to checkbox for nr 8']")).click();
I would like to create a string for the final xpath so you only have to change the text you'd like to click to change the test, something like:
String text = "Text next to checkbox for nr 8"; /** variable text based on what you want to click */
String locator = "//*[#class='settingswidgets' and text()='";
String xpathitem = locator + text + "']";
driver.findElement(By.xpath(xpathitem)).click();
This is the HTML:
<td class="settingsPanelTD" width="33%">
<div class="settingwidgetsTitle">
<input id="widgetsettings8" class="settingwidgets" type="checkbox" alt="2">
<span>Text next to checkbox for nr 8</span>
<a class="AddWidget" href="#"></a>
</div>
</td>
<td class="settingsPanelTD" width="33%">
<div class="settingwidgetsTitle">
<input id="widgetsettings9" class="settingwidgets" type="checkbox" alt="2">
<span>Text next to checkbox for nr 9</span>
<a class="AddWidget" href="#"></a>
</div>
</td>
<td class="settingsPanelTD" width="33%">
<div class="settingwidgetsTitle">
<input id="widgetsettings9" class="settingwidgets" type="checkbox" alt="2">
<span>Text next to checkbox for nr 10</span>
<a class="AddWidget" href="#"></a>
</div>
</td>
I'm using eclipse, Selenium and Java.
The XPaths you are using are incorrect. The third XPath you are using is closest to the correct solution:
//*[#class='settingswidgets' and text()='Text next to checkbox for nr 8']
In plain English, your XPath means - look for any element in the document with a class="settingswidgets" and text equal to Text next to checkbox for nr 8. Unfortunately, no such element exists.
One potential XPath you could use is:
//span[text()="Text next to checkbox for nr 8"]
This searches for any span element with the appropriate text.
You could then use:
String text = "Text next to checkbox for nr 8";
String locator = "//span[text()='";
String xpathitem = locator + text + "']";
driver.findElement(By.xpath(xpathitem)).click();
This should generate the desired click.
I don't have enough reputation to add comment
but in case you are unable to select option by clicking Span tag you need to click on input tag
ArrayList<WebElement> al=new ArrayList<WebElement>();
driver.findElements(By.className("settingwidgetsTitle"));
for(int i=0;i<al.size();i++){
if(driver.findElement(By.xpath(".//div[#class='settingwidgetsTitle']/span")).getText().equals("Option to Select")){
driver.findElement(By.xpath(".//div[#class='settingwidgetsTitle']["+i+"]
/input").click());
break;
}}

How to create a dynamic URL in SPRING MVC

I have a requirement to open a PDF when the user clicks on a particular employee id present in a table. Like:
Employee id url
123 View
234 View
When user clicks on the View corresponding to that row, details of Employee id should open in a pdf.
Someone please give me pointers on how to move forward on this. I am using JAVA Spring MVC framework.
Also need to know how will I create VIEW hyperlink, as this comes in a coulmn of a table. I am populating this table from Java Class.
My Controller Class:
#RequestMapping
public ModelAndView getHeaders(PortletRequest portlestRequest, PortletResponse portletResponse){
TableDAO dao = new TableDAO();
List<String> headersList = dao.getHeaders();
TableView tableView = new TableView();
tableView.setGetHeaderCount(headersList.size());
//System.out.println("tableView::");
tableView.setTableHeaders(headersList);
List prepaidBillingDetailsList = new ArrayList();
prepaidBillingDetailsList = dao.getPrepaidBillingInfo();
tableView.setPrepaidBillingDetailsList(prepaidBillingDetailsList);
return new ModelAndView("tableView", "tableView", tableView);
}
My JSP:
<table border="1px" bordercolor="black" width=80% align="center">
<tr>
<c:forEach var = "headerList" items = "${tableView.tableHeaders}">
<th>
${headerList}
</th>
</c:forEach>
</tr>
<c:forEach var = "headerList" items = "${tableView.prepaidBillingDetailsList}">
<tr>
<c:forEach var = "headerList" items = "${headerList.stringlst}">
<td>
${headerList}
</td>
<td>
<a href="<c:url value="editEmployee.htm">
<c:param name="msisdn" value="${tableView.msisdn}"/>
</c:url> ">Edit</a>
</td>
</c:forEach>
</tr>
</c:forEach>
</table>
In this, First headerList will get my eadrs of the table, Next header list will display the data for of my employee class. Now in the last coulmn i need inks, which will take me to the PDF of that particular employee.
You can form your view link url something like www.appdomain.com/App/Profile?id=123
view
and then map your controller with this url and get the id parameter from url and with the id get the details of the user and display it.
Second way is you can also get the url like www.appdomain.com/App/Profile/123
view
i.e. id as a path variable and get this path variable in the controller and get the details and display.

How to set the checkbox in the first column based on the value in the second column of a table?

I'm automating a task using Java and Selenium.
I want to set a checkbox (which is in the first column of a table) based on whether the value in the second column matches my input value. For example, in the following code snippet, the value "Magnus" matches my input value so I want to set the checkbox associated with it.
<table class="cuesTableBg" width="100%" cellspacing="0" border="0" summary="Find List Table Result">
<tbody>
<tr class="cuesTableBg">
<tr class="cuesTableRowEven">
<tr class="cuesTableRowOdd">
<td align="center">
<input class="content-nogroove" type="checkbox" name="result[1].chked" value="true">
<input type="hidden" value="1c62dd7a-097a-d318-df13-75de31f54cb9" name="result[1].col[0].stringVal">
<input type="hidden" value="Magnus" name="result[1].col[1].stringVal">
</td>
<td align="left">
<a class="cuesTextLink" href="userEdit.do?key=1c62dd7a-097a-d318-df13-75de31f54cb9">Magnus</a>
</td>
<td align="left"></td>
<td align="left">Carlsen</td>
<td align="left"></td>
</tr>
<tr class="cuesTableRowEven">
</tbody>
</table>
But I'm unable to do it. In the above case, the following two lines serve the purpose (as my input value matches with that in the second row):
WebElement checkbox = driver.findElement(By.xpath("//input[#type = 'checkbox' and #name = 'result[1].chked']"));
checkbox.click();
But it can't be used as the required value might not always be in the second row.
I tried following code block but to no avail:
List<WebElement> rows = driver.findElements(By.xpath("//table[#summary = 'Find List Table Result']//tr"));
for (WebElement row : rows) {
WebElement userID = row.findElement(By.xpath(".//td[1]"));
if(userID.getText() == "Magnus") {
WebElement checkbox = row.findElement(By.xpath(".//input[#type = 'checkbox']"));
checkbox.click();
break;
}
}
For what it's worth, XPath of the text in the second column:
/html/body[#id='mainbody']/table/tbody/tr/td/div[#id='contentautoscroll']/form/table[2]/tbody/tr[3]/td[2]/a
I don't know about CSS Selectors. Will it help here?
If you know the input value already you just use below xpath to select respected checkbox
"//a[text(),'Magnus']/parent::td/preceding-sibling::td/input[#type='checkbox']"
Update:
"//a[text()='Magnus']/parent::td/preceding-sibling::td/input[#type='checkbox']"
While comparing two strings equals should be used instead of ==
Replace
if(userID.getText() == "Magnus")
with
String check1 = userID.getText();
if(check1.equals("Magnus")
Seems like it was a silly mistake on my part. The following code snippet, a fairly straightforward one, worked.
List<WebElement> rows = driver.findElements(By.xpath("//table[#class='cuesTableBg']//tr"));
for (WebElement row : rows) {
WebElement secondColumn = row.findElement(By.xpath(".//td[2]"));
if(secondColumn.getText().equals("Magnus")) {
WebElement checkbox = row.findElement(By.xpath(".//td[1]/input"));
checkbox.click();
break;
}
}

Error in my struts Action class

I have a JSP where I am showing date and description from database. Every entry has a unique id, but I am not showing on the page(showing checkbox)
These entries are thrown using a "logic:iterate", so the number of rows is always changing based on entries.
Now these fields are shown as a text field so that the user can also update the date or description. A checkbox is to the left so the
user can select what all values they want to update. Remember the logic:iterate above, the checkbox has to be defined using name and
cannot have id.
...
...
<logic:notEmpty name="specialResult" scope="request">
<logic:iterate name="specialResult" id="specialResult" indexId="index">
<tr align="center">
<td width="15%">
<input type="checkbox" name="upisActive" property="upisActive"
value="<bean:write name="specialResult" property="upId"/>"></input></td>
<td width="15%"><input type="text" name="upDate" value="<bean:write name="specialResult" property="upDate"/>"
property="upDate" size="20" class="Date" id="Date"></input></td>
<td width="15%"><input type="text" name="upDesc" value="<bean:write name="specialResult" property="upDesc"/>"
property="upDesc" size="20" id="Desc"/></td>
</tr>
</logic:iterate>
...
My error is that if I have three rows and I want to update third row and select third checkbox. My Action class is retrieving the first row date and desc.
How can I edit my action class to retrieve the value against the checked checkboxes?
public ActionForward class(ActionMapping mapping, ActionForm theForm,
HttpServletRequest request, HttpServletResponse response) throws IOException,
SQLException, ServletException
{
Connection conn = null;
Service Serv = new Service();
List updList = new ArrayList();
Form upForm = (Form) theForm;
String[] values = request.getParameterValues("upisActive");
try
{
conn = getConnection(request, false);
for (int i=0;i<values.length;i++){
VO hdvo = new VO(); //Vo class with getters and setters
val = values[i];
hdvo.setDate(upForm.upDate[i]);
hdvo.setDesc(upForm.upDesc[i]);
updList.add(hdvo);
}
hdServ.updTest(updList, conn);
...
The problem is with how you've set up your page. You have all checkboxes with the same name (standard setup) but you also have the upDate and upDesc fields also set up with the same name.
That means that when you submit your form, on the server you will get (considering your example) a list of 3 upDate values, a list of 3 upDesc values and a list of 3 upisActive checkboxes. Well... not quite!
The problem is your checkboxes and the code you use to read the values to update.
First, checkboxes are not sent on the request if they are not checked. That means that, depending on your selection, on the server you will get a list of upisActive values of length 0, 1, 2 or 3.
Second, you then have this code on the server:
String[] values = request.getParameterValues("upisActive");
...
for (int i = 0; i < values.length; i++) {
...
val = values[i];
hdvo.setDate(upForm.upDate[i]);
hdvo.setDesc(upForm.upDesc[i]);
...
}
In you example, you check the third checkbox and submit your form. That means that String[] values will be of length 1 because only the selected checkbox is send to the server. But the input fields are always sent in 3 upDesc and 3 upDate.
Then you loop-it (once) and extract upForm.upDate[0] and upForm.upDesc[0]. This way, you update the first row by checking the third checkbox.
Other problems:
1) You have used the same identifier in the following code (it's asking for trouble):
<logic:iterate name="specialResult" id="specialResult"...
2) You are using classic inputs and added property attribute to it:
<input type="text" ... property="upDate" />" property="upDate" ...
3) Not sure that the browser guaranties that the fields will be sent in the exact matching order each time, so using a single counter is, I guess, just "hoping" for the same order.
4) Also, read this

Categories