Row Selection in Enhanced Grid - dojo

I am new to Dojo and i came across a problem that has me completely stumped. I am creating a data grid in Dojo with the Enhanced Grid .
Each row in the grid has a checkbox with which the row can be selected. The checkbox has been implemented using the indirectselection plugin.
Now when i select a row using the checkbox everything works fine. But when I select a row by clicking on other data cells the row does'nt get selected !
Heres the JSP part of the datagrid
<table data-dojo-id="grid" data-dojo-type="dojox.grid.EnhancedGrid" plugins="{indirectSelection: {headerSelector:true}, filter: true,pagination: true}"
data-dojo-props="store:icGrid,
clientSort:true " formatterScope="myFormatters"
style="width: 100%; height: 20em;">
<thead>
<tr>
<th width="25%" field="empNo" formatter="formatLink">empNo</th>
<th width="25%" field="name">name</th>
<th width="25%" field="email">email</th>
<th width="25%" field="phone">phone</th>
</tr>
</thead>
</table>
If I remove the code referring to indirect selection (plugins="{indirectselection...) the rows get selected when I click on other data cells (as they should). But I also need the checkbox that the indirectselection implements.
Is there a way to make the indirectselection work without taking away the row select functionality ?
Take a look at the grid in the page I will link below. I need a grid that works like that
(The last grid in the page with the checkboxes)
http://dojotoolkit.org/documentation/tutorials/1.8/working_grid/demo/selector.php

I managed to resolve the issue by 1. using the cellClick event to listen 2. Get the rowindex of the cell when it is clicked 3. set it to selected.
grid.on("CellClick", function(event)
{
var rowId = event.rowIndex;
grid.selection.setSelected(rowId, true);
grid.render();
}
grid.selection.getSelected(); did not return the selected rows and I am wondering if this is a compatibility issue ? It seems like when i use the indirectSelection plugin the row Select is behaving in unexpected ways.

Have you ever heard about DGRID .
I think you should check it.
It really works very good with dojo .
Here are some useful sites .
Dgrid Main webpage
Git hub Documentation

Use this code below to listen to grid selection and check what selectedRows return and use the index of that row to toggleRow
dojo.connect(grid, "onRowClick", function(e) {
var selectedRows= grid.selection.getSelected();
grid.rowSelectCell.toggleRow(selectedRows[i], true);
});

Simple code :- "SelectionChanged"` even is available. so code like this:-
grid.on("SelectionChanged", function(event)
{
var rowId = event.rowIndex;
grid.selection.setSelected(rowId, true);
grid.render();
}

The "SelectionChanged"` even is available. so code like this:-
grid.on("SelectionChanged", function(event)
{
var rowId = event.rowIndex;
grid.selection.setSelected(rowId, true);
grid.render();
}

Related

How to handle Table row selected changed?

How to handle row selected changed event for a table using Blazor?
I tried handling #onchange as well as #onselectionchange.
The syntax for the table looks like this:
<table class="table" #onchange="#this.SelectionChanged">
Your event binding doesn't work because the table element does not emit change events.
Instead, you could add an input element (for example a checkbox) inside your table rows. You can then handle row selection changes by adding your event binding to the input elements.
Read more on the HTMLElement change event in this article.
You can use Onclick in the row:
<tbody>
#foreach (var item in Forecasts)
{
<tr class="#item.Clase" #onclick="#(() => DoSomething(item))">
<td>#item.Date</td>
<td>#item.TemperatureC</td>
<td>#item.TemperatureF</td>
<td>#item.Summary</td>
</tr>
}
</tbody>
and create a Dosomething to receive the item

Improvement With Xpath Search?

I am a student learning selenium and trying to set a checkbox(by placing a tick) that resides on the same row as a target document. Here is how the row looks:
<span><input>Checkbox</input></span> - <span>_lblDocumentCategoryDescription</span> - <span>_lblDocumentdescription</span>
Each row consists of a checkbox for that row, a category and a description. I am provided the description and need to set the corresponding checkbox at the beginning of the row.
Although I have a solution that works I am looking for a better method as my method is very slow and I can call it multiple times, compounding the slowness. The page in question has 315 fixed different documents that might possibly be added (to a merge and print feature). I usually add at least 3 rows so need to run the search
I am currently using xpath to search since my knowledge of CSS is limited and it seems like traversing up the DOM (no :parent?) is not easy unless using some javascript, which I am trying to avoid. I have read that executing JS doesn't emulate the user correctly so I guess xpath is the solution?
As I know there must be a quicker/better/more efficient solution I am hoping others might have found better?
Here is what I am currently using:
Method Call
CPTools,setStupidCheckbox("Sublease Addendum", true);
Method:
public CPTools setStupidCheckbox(String documentToPrint, Boolean onIfTrue) {
this.log.trace("Starting: setStupidCheckbox; parameter: documentToPrint " + documentToPrint);
String xpathForCheckboxes = "/ancestor::tr//input";
try {
String xpathForDocumentDescriptions = String.format("//span[contains(text(), '%s')]", documentToPrint);
tools.waitForElement(By.xpath(xpathForDocumentDescriptions), 2);
if (driver.findElement(By.xpath(xpathForDocumentDescriptions)).isDisplayed()) {
driver.findElementByXPath(xpathForDocumentDescriptions + xpathForCheckboxes).click();
}
} catch (org.openqa.selenium.NoSuchElementException | ElementNotVisibleException e) {
}
this.log.trace("Ending: setStupidCheckbox");
return this;
}
Here is the full xpath for a table row (the dynamic part of the id is the _ctl316):
<tr class="DataGridCellData">
<td class="DataGridCellDataCenterAligned">
<span class="DataLabel"><input id="ctl01_PageBody_grdDocument_ctl316_chkSelect" name="ctl01$PageBody$grdDocument$ctl316$chkSelect" onclick="javascript:uiHelper.GridCellCheck(this, 'chkAllSelect');" type="checkbox"></span>
</td><td>
<span id="ctl01_PageBody_grdDocument_ctl316_lblDocumentCategoryDescription">Approval Form</span>
</td><td align="left">
<span id="ctl01_PageBody_grdDocument_ctl316_lblDocumentdescription">Sublease Addendum</span>
</td><td align="center">
</td>
</tr>
Thanks in advance for any possible help.
Try below XPath if span text (Sublease Addendum) is unique:
//td[.= 'Sublease Addendum']

HTML Table creation - when an event as occured

I have created an HTML Table. I need to display this table only when a button is clicked. Could some one suggest how to achieve this?
Regards
Giri
You can use jquery and attached an handler.
for example
in html:
<a class="button-link" href="javascript:void(0);">link</a>
<table class='hidden-table'>
<tr>
<th>id</th><th>name</th>
</tr>
<tr>
<td>1</td><td>Mr Awesome</td>
</tr>
</table>
in css:
.hidden-table{
display:none;
}
in js/jquery
$('.button-link').on('click',function(){
$('.hidden-table').show()
})
use the css to hide the table first and then upon clicking on the link it will show the table.
You could use Jquery, from here http://jquery.com/download/ .
After installing, you could use the following syntax:
$('#idofthebutton').click(function(){
$('#idofthetable').toggle();
});

How can I select checkboxes using the Selenium Java WebDriver?

How can I check the checkboxes using an id or XPath expression? Is there a method similar to select by visibletext for a dropdown?
Going through the examples given for all other related questions, I could not find a proper solution that works in a concise way that by few line or method I can check a chekbox or radio button.
A sample HTML section is below:
<tbody>
<tr>
<td>
<span class="120927">
<input id="ctl00_CM_ctl01_chkOptions_0" type="checkbox" name="ctl00$CM$ctl01$chkOptions$0"/>
<label for="ctl00_CM_ctl01_chkOptions_0">housingmoves</label>
</span>
</td>
</tr>
<tr>
<td>
<span class="120928">
<input id="ctl00_CM_ctl01_chkOptions_1" type="checkbox" name="ctl00$CM$ctl01$chkOptions$1"/>
<label for="ctl00_CM_ctl01_chkOptions_1">Seaside & Country Homes</label>
</span>
</td>
</tr>
</tbody>
Selecting a checkbox is similar to clicking a button.
driver.findElement(By.id("idOfTheElement")).click();
will do.
However, you can also see whether the checkbox is already checked. The following snippet checks whether the checkbox is selected or not. If it is not selected, then it selects.
if ( !driver.findElement(By.id("idOfTheElement")).isSelected() )
{
driver.findElement(By.id("idOfTheElement")).click();
}
It appears that the Internet Explorer driver does not interact with everything in the same way the other drivers do and checkboxes is one of those cases.
The trick with checkboxes is to send the Space key instead of using a click (only needed on Internet Explorer), like so in C#:
if (driver.Capabilities.BrowserName.Equals(“internet explorer"))
driver.findElement(By.id("idOfTheElement").SendKeys(Keys.Space);
else
driver.findElement(By.id("idOfTheElement").Click();
If you want to click on all checkboxes at once, a method like this will do:
private void ClickAllCheckboxes()
{
foreach (IWebElement e in driver.FindElements(By.xpath("//input[#type='checkbox']")))
{
if(!e.Selected)
e.Click();
}
}
Solution for C#
try
{
IWebElement TargetElement = driver.FindElement(By.XPath(xPathVal));
if (!TargetElement.Selected)
{
TargetElement.SendKeys(Keys.Space);
}
}
catch (Exception e)
{
}
You can use the following code:
List<WebElement> checkbox = driver.findElements(By.name("vehicle"));
((WebElement) checkbox.get(0)).click();
My HTML code was as follows:
<.input type="checkbox" name="vehicle" value="Bike">I have a bike<br/>
<.input type="checkbox" name="vehicle" value="Car">I have a car<br/>
To get the checkbox for 'Seaside & Country Homes', use this XPath:
//label[text()='Seaside & Country Homes']/preceding-sibling::input[#type='checkbox']
To get the checkbox for 'housingmoves', use this XPath:
//label[text()='housingmoves']/preceding-sibling::input[#type='checkbox']
The principle here is to get the label with the text you want, then get the checkbox that is before the label, since that seems to be how your HTML is laid out.
To get all checkboxes, you would start a little higher up and then work down, so that is to say get the table, and then get any checkbox within a span:
//table/descendant::span/input[#type='checkbox']
I found that sometimes JavaScript doesn't allow me to click the checkbox because was working with the element by onchange event.
And that sentence helps me to allow the problem:
driver.findElement(By.xpath(".//*[#id='theID']")).sendKeys(Keys.SPACE);
This should help -
IWebElement elementToClick = driver.findElement(By.xpath(""//input[contains(#id, 'lstCategory_0')]"));
elementToClick.Click();
You can also pass an id.
If you want something like visible text you can "find element" by name if they have names.
The below code will first get all the checkboxes present on the page, and then deselect all the checked boxes.
List<WebElement> allCheckbox = driver.findElements(By
.xpath("//input[#type='checkbox']"));
for (WebElement ele : allCheckbox) {
if (ele.isSelected()) {
ele.click();
}
}
A solution using WebDriver and C# is below. The key idea is to get the ID of the checkbox from the labels' 'for' attribute, and use that to identify the checkbox.
The code will also set the checkbox state only if it needs to be changed.
public void SetCheckboxStatus(string value, bool toCheck)
{
// Get the label containing the checkbox state
IWebElement labelElement = this.Driver.FindElement(By.XPath(string.Format("//label[.='{0}']",value)));
string checkboxId = labelElement.GetAttribute("for");
IWebElement checkbox = this.Driver.FindElement(By.Id(checkboxId));
if (toCheck != checkbox.Selected)
{
checkbox.Click();
}
}
Maybe a good starting point:
isChecked = driver.findElement((By.id("idOftheElement"))).getAttribute("name");
if(!isChecked.contains("chkOptions$1"))
{
driver.FindElement(By.Id("idOfTheElement")).Click();
}
Running this approach will in fact toggle the checkbox; .isSelected() in Java/Selenium 2 apparently always returns false (at least with the Java, Selenium, and Firefox versions I tested it with).
The selection of the proper checkbox isn't where the problem lies -- rather, it is in distinguishing correctly the initial state to needlessly avoid reclicking an already-checked box.
To select a checkbox, use the "WebElement" class.
To operate on a drop-down list, use the "Select" class.
Step 1:
The object locator supposed to be used here is XPath. So derive the XPath for those two checkboxes.
String housingmoves="//label[contains(text(),'housingmoves')]/preceding-sibling::input";
String season_country_homes="//label[contains(text(),'Seaside & Country Homes')]/preceding-sibling::input";
Step 2:
Perform a click on the checkboxes
driver.findElement(By.xpath(housingmoves)).click();
driver.findElement(By.xpath(season_country_homes)).click();
For a partial match, do the following:
getDriver().findElement(By.cssSelector("<tag name>[id*='id pattern to look for']")).click();
Here is the C# version of Scott Crowe's answer. I found that both IEDriver and ChromeDriver responded to sending a Key.Space instead of clicking on the checkbox.
if (((RemoteWebDriver)driver).Capabilities.BrowserName == "firefox")
{
// Firefox
driver.FindElement(By.Id("idOfTheElement")).Click();
}
else
{
// Chrome and Internet Explorer
driver.FindElement(By.Id("idOfTheElement")).SendKeys(Keys.Space);
}
I tried with various approaches, but nothing worked. I kept getting "Cannot click element" or ElementNotVisibleException.
I was able to find the input, but I couldn't check it. Now, I'm clicking on the div that contains the checkbox and it works with following HTML (CSS based on Bootstrap).
#foreach (var item in Model)
{
<tr>
<td>
<div id="#item.Id" class="checkbox">
<label><input type="checkbox" class="selectone" value="#item.Id"></label>
</div>
</td>
<td val="#item.Id">
#item.Detail
</td>
<td>
<div>#item.Desc
</div>
</td>
<td>
#Html.ActionLink("Edit", "Create", new { EditId = item.Id })
</td>
</tr>
}
This is the code for WebDriver:
var table = driver.FindElement(By.TagName("table"));
var tds = table.FindElements(By.TagName("td"));
var itemTds = tds.Where(t => t.Text == itemtocheck);
foreach (var td in itemTds)
{
var CheckBoxTd = tds[tds.IndexOf(td) - 1];
var val = td.GetAttribute("val");
CheckBoxTd.FindElement(By.Id(val)).Click();
}
In this approach, I give the item id as id for the div and also add an attribute for td with that id. Once I find the td of the item that needs to be checked, I can find the div before that td and click it. We can also use the XPath query that supports before (here is the example http://learn-automation.com/how-to-write-dynamic-xpath-in-selenium/).

How to migrate a dojo (dojo 0.x) FilteringTable to a DataGrid in (dojo 1.6)?

Im migrating and extending an existing Web Application based on a very old Dojo Framework.
Declarative Setup of the table:
OLD
<table dojoType="FilteringTable" id="dataTable"
valueField="f_id" multiple="false" alternateRows="true">
<thead><tr>
<th field="f_fname">Firstname</th>
<th field="f_lname">Lastname</th>
</tr></thead>
</table>
NEW
<table dojoType="dojox.grid.DataGrid" id="dataTable">
<thead><tr>
<th field="f_fname">Firstname</th>
<th field="f_lname">Lastname</th>
</tr></thead>
</table>
Initializing Table Store:
OLD
var tab = dojo.widget.byId("dataTable");
if(tab){
tab.store.setData([]);
}
NEW
var tab = dijit.byId("dataTable");
if(tab){
if(!tab.store){
tab.store = new dojo.store.Memory({data:[]});
}
else{
tab.store.setData([]);
}
}
Refreshing the Data:
OLD/NEW
tab.store.setData(result.array);
The old version Table is filled with the Data, the new version table remains empty.
The Data array retrieved in both cases is exactly the same.
So I wonder what differences should be adressed between the store used in the old FilteringTable and the store api used for the new dojox DataGrid.
Since I am new to using data stores in general I might be missing some crucial parts.
Visually the new Grid seems to be fully functual.
update
tab.update(); // tab = dojox.grid.DataGrid
does nothing to bring the visual part up to date.
Shouldn't the DataGrid update when the store data changes, or is there some manual action necessary?
In fact the DataGrid does not seem to react to changes in the Memory-Store at all. Maybe there is some wiring missing here?
update
I have been wiring up the Grid with a Memory store declaratively:
<div dojoType="dojo.store.Memory" jsId="memStore"></div>
<table dojoType="dojox.grid.DataGrid" id="dataTable" store="memStore">
<thead><tr>
<th field="f_fname">Firstname</th>
<th field="f_lname">Lastname</th>
</tr></thead>
</table>
First thing that I get is an error in _setStore() in DataGrid.js saying:
this.store.getFeatures is not a function
.
Is it possible that DataGrid is not compatible with all stores?
I was of the impression that the store api was standardized in 1.6.
If so, is there an alternative Store to use with javascript array input.
(as seen above)
A friendly poster on an other Forum (Millennium) has provided me with an answer:
Since Dojo 1.6 there is a new Access Scheme for stores in Dojo.
Since dojox.grid.DataGrid does not support those stores directly there is a wrapper Class provided in dojo.data called dojo.data.ObjectStore.
So in order to get my Memory Store to work it would need to be initialized with:
var tab = dijit.byId("dataTable");
if(tab){
if(!tab.store || !tab.store.objectStore){
tab.store = new dojo.data.ObjectStore({
objectStore : new dojo.store.Memory({data:[]})
});
}
else{
tab.store.objectStore.setData([]);
}
}
and updated with:
tab.store.objectStore.setData(result.array);
However there is still a little shortcoming at the moment:
The Grid does not update its data autmatically, but only after sorting a column.
Using tab.update() does not work.
update
When changing the data with objectStore.put() or objectStore.setData() I now use the _refresh() function of the Grid afterwards.
While it is a private function I still have no better way to update the Grid.