Angular 2 Primeng Datatable- single (exclusive) row selection on click - primeng-datatable

I am using a Primeng datatable to display editable entries from a database. When a row is clicked, a new component is displayed to allow editing of the associated data for the row. When a new row is clicked, the component will show the data for that row instead, and so on.
Obviously, this is exclusive- only one row can be selected at a time. I want to highlight the currently 'active' row in a different color, so when a new row is selected any previously hightlighted row should be reset to its default color.
At present I have the following in my template:
<p-dataTable [value]="rowData" [rowStyleClass]="highlightSelectedRow" [rowHover]="true" (onRowClick)="rowClick($event)">
<ng-template ngFor let-col [ngForOf]="cols">
<p-column [field]="col.field" [header]="col.header"></p-column>
</ng-template>
</p-dataTable>
...and in my component:
rowClick($event){
const rowData = $event.data;
rowData.selected = !rowData.selected;
// and do some other stuff...
}
highlightSelectedRow(rowData: any, rowIndex: number){
return (rowData.selected) ? 'selected' : '';
}
...CSS to style selected row:
.row.selected {
background-color: red;
}
This works insofar as highlighting the clicked row, but highlighted rows remain highlighted, and I'm wondering about the best way to reset them.
I guess I could loop through all the rows of data and find the row with selected property set to true and set it to false, but this seems a rather inefficient way of doing it, especially if I am dealing with many thousands of rows of data.
Am I missing a better, built-in way of doing this with Primeng?

This works insofar as highlighting the clicked row, but highlighted rows remain highlighted, and I'm wondering about the best way to reset them.
Create a class for unselected row such as
.row.unselected {
background-color: white;
}
and affect this class whenever you unselect a row
highlightSelectedRow(rowData: any, rowIndex: number){
return (rowData.selected) ? 'selected' : 'unselected';
}
See this simular SO question or Plunker for more details.

I have this scenario:
HTML:
<p-dataTable class="table table-responsive" #dealData [value]="dealList" sortMode="multiple"
[(selection)]="selectedDeals"
dataKey="hncId" scrollable="true" scrollHeight="540px" [rowStyleClass]="highlightSelectedRow"
styleClass="table" [paginator]="true" [rows]="100" [pageLinks]="5">
....
<p-column [header]="'Details' | translate" [style]="{'text-align': 'center'}">
<ng-template let-row="rowData" pTemplate type="body">
<button type="button" (click)="showDealDetail(row)" (mouseover)="row.selected = !row.selected" (mouseout)="row.selected = !row.selected" class="viewButton" pButton
[label]="'View' | translate"></button>
</ng-template>
</p-column>
...
</p-dataTable>
Component:
highlightSelectedRow(rowData: any, rowIndex: number) {
return (rowData.selected) ? 'rowSelected' : '';
}
CSS:
tr.rowSelected > td {
background-color: #ebf8ee !important;
}
This highlights one row at a time. Key is (mouseover) and (mouseout).

Related

Setting empty string in headerText attribute

I have JSF data table and only one column has column header.
I need to hide the column with header text based on the condition and when I do that the entire header row shrinks because the other columns don't have header text.
To prevent this, I need to set 'empty' string and I tried a few tricks but nothing seem to work.
<p:dataTable ....>
<p:column headerText=" " >
How do I set empty string headerText attribute?
Thx in advance.
Depending on your Primefaces version you could use this code to force the creation of the html element
<p:dataTable ....>
<p:column headerText=" " >
With early version this should create the div but make it very small, so you can add css style to adjust to your wish, something like
.ui-datatable thead th {
min-height: xx px;
min-width: yy px;
}
I think you can solve your problem event with only the second part, so only with css.

VBA - Trying to Input text and click Search button, All within a Table, within a Form, No ID Element, only Class Element

Trying to input a Value into an Input Box and press the Search button to get the results from a table.
I can't seem to figure out how to input the Value into the Box. The input box and button seems to be inside a form inside a table. No ID element.
**> Input Box has these properties**
<td Class = "searchRow">
<input type = "text" name = "name" value onblur = "Numberfield();" style = "width: 200px;" class = "required">
This is all inside Form ID "SearchForm" > div ID "Search" > Tr > Td CLass "searchRow"
After I grab the correct internet explorer tab, I need to getElementByClassName and inp9ut value
IE.Document.getElementsByTagName("tr").getElementsByTagName("input").Value = "Search"
IE.Document.getElementsByClassName("searchRow").getElementsByTagName("input").Value = "Search"
I can't seem to get any combination to work.
Another element is the Button.
Button has these properties
<td colspan = "6" style = "align:right;" class = "searchonly">
<input type = "button" class = "actionbutton" value = "search" onclick = "submitform()">
How do i Click this button that is in the Table Row.
IE.Document.getElementsByClassName("searchonly").getElementsByTagName("actionbutton").Click
Does this make sense?
Appreciate the help.
Better to add ID attribute and then use getElementsByID.
And If that is not possible then you can use XPATH and get the element by using following function.
function getElementByXpath(path) {
return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
console.log( getElementByXpath("VALUE OF XPATH") );
And you can easily get the XPATH by using the extension in any browser. Like XPath Finder available in google chrome.
I write the Answer as comments and code:
'What you want first
'**> Input Box has these properties**
'<td Class = "searchRow">
' <input type = "text" name = "name" value onblur = "Numberfield();" style = "width: 200px;" class = "required">
'This is all inside Form ID "SearchForm" > div ID "Search" > Tr > Td CLass "searchRow"
'What you try
'IE.Document.getElementsByTagName("tr").getElementsByTagName("input").Value = "Search"
'IE.Document.getElementsByClassName("searchRow").getElementsByTagName("input").Value = "Search"
'What should work
'Attention: the get methods work case sensitive. It's a difference between "Search" and "search"
'I write that because I wonder if the first letter of the ID "Search" is upper case in the original document
'
'You can seperate the div tag include all inner tags as own DOM object
Dim nodeDivSearch As Object
Set nodeDivSearch = IE.Document.getElementByID("Search")
'
'Now you can work on the new DOM object only
'Note that the getElements methods always create a NodeCollection
'All elements of the collection have an index. The first element always has
'index 0, so you can access the first input tag in the new DOM object as follows
'(getElementByID does not create a NodeCollection, because an ID should always
'be unique. So there is only one element for this criterion anyway)
nodeDivSearch.getElementsByTagName("input")(0).Value = "Search"
'
'I think your code will work with setting indexes
IE.Document.getElementsByClassName("searchRow")(0).getElementsByTagName("input")(0).Value = "Search"
'What you want second
'Button has these properties
'<td colspan = "6" style = "align:right;" class = "searchonly">
' <input type = "button" class = "actionbutton" value = "search" onclick = "submitform()">
'What you try:
'IE.Document.getElementsByClassName("searchonly").getElementsByTagName("actionbutton").Click
'I think you know what to do here
IE.Document.getElementsByClassName("searchonly")(0).getElementsByTagName("actionbutton")(0).Click
getElementsByClassName returns an array-like object of all child elements which have all of the given class names. So you need to choose which element you need using index in the returned array. So does it with getElementsByTagName.
So if the html code is like below:
<form id="SearchForm">
<div id="Search">
<table>
<tr>
<td Class="searchRow">
<input type="text" name="name" value onblur="Numberfield();" style="width: 200px;" class="required" id="a1">
</td>
<td colspan="6" style="align:right;" class="searchonly">
<input type="button" class="actionbutton" value="search" onclick="submitform()">
</td>
</tr>
</table>
</div>
</form>
Then the vba code to set value and click button should be like below:
IE.Document.getElementsByClassName("searchRow")(0).getElementsByTagName("input")(0).Value = "Search"
IE.Document.getElementsByClassName("searchonly")(0).getElementsByClassName("actionbutton")(0).Click
The code above is just for example, you should change the index according to the actual situation of the website you visit.

How can I initially hide columns in a p:dataTable with p:columnToggler

I'm using PrimeFaces v.5 with this version a new component is released that ColumnToggler, when view is rendered, refreshed all checkbox are checked as a default operation.
What I need to do is;
to uncheck some columns when I initialize the view,
make p:columnToggler remember checked and unchecked options when a refresh operation occurs on p:dataTable
In Primefaces 5.2 you can set the p:column visible attribute to false
<p:column ... visible="false">
You can ofcourse use EL in the visible attribute by colum index (reordering becomes more difficult)
<p:column ... visible="#{visibilityModel.visibleList[1]}">
It hides the column at the beginning depending on the return value and you can show/hide the column through the columnToggler checkbox
By using the ajax toggle event
<p:ajax event="toggle" listener="#{viewBean.onToggle}" />
You can update the state of the visibilityModel server side
public void onToggle(ToggleEvent e) {
list.set((Integer) e.getData(), e.getVisibility() == Visibility.VISIBLE);
}
See this PrimeFaces blog entry for full example to actually keep/store the state of the visibility server side so it can be reused later
The best solution depends on the PrimeFaces version you are using.
PrimeFaces >= 5.2
See the other answer in this question.
workaround for < 5.2
You need to solve the first problem manually by overriding Primefaces' own ColumnToggler.prototype.render() function
first add styleClass="not-show-at-start" to your column that you want to insvisibe at start to access in javascript render() function;
<!--This column will not be shown at start-->
<p:column headerText="Cloumn to hide initially" width="70" styleClass="not-show-at-start">
<h:outputText value="#{entityVar.nmProcessOwner}" />
</p:column>
<!--This column will be shown at start-->
<p:column headerText="Column to show initially" width="70">
<h:outputText value="#{entityVar.nmProcessOwner}" />
</p:column>
secondy create a javascript file and paste code below in it, this function will re assign render function of ColumnToggler
PrimeFaces.widget.ColumnToggler.prototype.render = function() {
//variable for creating id referance for each checkbox in ColumnToggler
var id=0;
this.columns = this.thead.find("> tr > th:visible:not(.ui-static-column)");
this.panel = $("<div></div>").attr("id", this.cfg.id).addClass("ui-columntoggler ui-widget ui-widget-content ui-shadow ui-corner-all").append('<ul class="ui-columntoggler-items"></ul').appendTo(document.body);
this.itemContainer = this.panel.children("ul");
for (var a = 0; a < this.columns.length; a++) {
id++;
var b = this.columns.eq(a);
$('<li class="ui-columntoggler-item"><div class="ui-chkbox ui-widget"><div id="cb'+id /*creating id for each checkbox for accessing later*/+'" class="ui-chkbox-box ui-widget ui-corner-all ui-state-default ui-state-active"><span class="ui-chkbox-icon ui-icon ui-icon-check"></span></div></div><label>' + b.children(".ui-column-title").text() + "</label></li>").data("column", b.attr("id")).appendTo(this.itemContainer);
//access clumns using class reference(not-show-at-start) created in jsf page
if(b.hasClass( "not-show-at-start")){
//access checkbox using id attribute created above and uncheck it
//this will hide columns that have "not-show-at-start" class
this.uncheck($('#cb'+id));
}
}
this.hide();
}
An alternative solution could be to set directly the checkbox you want to uncheck after you load the page. It's a less elegant solution but it works. I did it this way:
<h:body onload="javascript:
$('.ui-chkbox-box')[18].click();">
By this way, after loading the page, javascript hide the column referenced by chechbox number 18 but the checkbox is still present on the columnToggler for the user to check it and show the column again if he wants to.
Greetings
Complementing Damián answer:
$(function() {
$('.ui-columntoggler-items .ui-chkbox .ui-chkbox-box').click();
});
This will do the job, clicking the columntoggler chkbox after page load..
#Edit
You should set as toggleable="false" the columns you don't want to hide (always displayed)
Reason: if you use the javascript method to "override" primefaces toggler, sometimes the datatable column shown can be displayed wrong in the layout (out of the table size, for an example, like happened with me), that's why i decided to use the method described above..

rich:autocomplete truncates selected text for display

I have a rich:autocomplete dropdown selector in my application. In the dropdown list that appears as the user begins entering text, the strings that have been loaded into the list of selections will happily display out to the entire width of the dropdown. However, once you make a selection only about 34 characters of the string will be displayed, with the result that the end user has to scroll left and right in the input box to see the entire string, see here (StackOverflow won't allow me to post inline images yet): http://imgur.com/Y9LLaBi
Here's the offending table cell in the frontend XHTML file. It uses the JSF and richfaces namespaces and there's a backing bean that creates the autocomplete suggestion list and executes other business logic, but I believe this is the only relevant code:
<td height="20" class="addborderright addborderbottom inputbox" colspan="4">
<!-- nb: richfaces autocomplete to ensure proper name entry -->
<h:message styleClass="errormsg" for="campusName" />
<rich:autocomplete id="campusName" length="50" mode="client" minChars="1"
layout="table" autofill="true" selectFirst="true"
onselectitem="javascript:executeAction(
'#studentComplaintCampusInformationBean.formName}',
'populateCampusAddressFieldsLink');"
value="#{studentComplaintCampusInformationBean.campus.operatingName}"
autocompleteList="#{studentComplaintCampusInformationBean.registeredCampusNameList}"
style="width:370px" fetchValue="#{fn}" var="fn" maxlength="100">
<rich:column>#{fn}</rich:column>
</rich:autocomplete>
</td>
To make the dropdown box left-justify text and be the same as the width of the input field the following CSS is at the top of the XHTML file:
<style>
.rf-au-fnt{
text-align: left; float: left;
}
.rf-au-lst-dcrtn .rf-au-lst-scrl {
width: 370px; !important
}
</style>
However, there doesn't appear to be a CSS property relating to the width of the displayed text in the input box, so it appears cut off to the end user, and only fills about half the available space in the input box! Could someone please help? Thanks!
rf-au-fnt is the class of the input, you're already overriding it so just add the width.
As a sidenote, rather than directly overriding the RichFaces classes you should set a class for the component and then write stylesheets like
.myAutocomplete .rf-au-fnt {text-align: left; float: left; width: 370px !important
}
This way you don't change something you wouldn't want to.

Change Row Color Based On Condition In C#

Hi I'm very new to C#. But I have this weblist that print out some result, that I'm trying to change, What I'm trying to do is to make an if statement. If row[4] is less then [2] then the row should be red. I have tried to copy some of the code.
//##############Print result##############
foreach ( string[] row in dataResult)
{
//Birn.Util.cellDecimalPrinter(row[0],"#,0.0")
//<tr id="PopUp" onclick="OpenWindow('file.aspx?querystr=row[0]&date=textbox.text','500','300')">
%>
<tr>
<td><%=row[0]%></td>
<td><%=row[1]%></td>
<td><%=row[2]%></td>
<td><%=row[3]%></td>
<td><%=row[4]%></td>
</tr>
<%
}
You can change the style of the row using CSS. I have assumed that whatever you are comparing in rows 2 and 4 is a string representation of a Decimal: adjust the Convert.ToDecimal to the appropriate type if needed:
foreach ( string[] row in dataResult)
{
string redStyle= "";
If (Convert.ToDecimal(row[4]) < Convert.ToDecimal(row[2])) {
// ideally you would have a style defined in a separate CSS file for this
redStyle = " style=\"background-color: Red; color: White\"";
}
}
%>
<tr<%=redStyle%>>
<td><%=row[0]%></td>
<td><%=row[1]%></td>
<td><%=row[2]%></td>
<td><%=row[3]%></td>
<td><%=row[4]%></td>
</tr>
<%
}

Resources