I have a field called ID-Text that varies in length from 1 to 3000 words stored in a database. I want to display that in a form. Based on its size I want to vary the size of the <h:inputTextarea>. How can I do it.. will I be able to set row property from bean?
The <h:inputTextarea> supports both cols and rows attributes, as you can see from the VLD. Example:
<h:inputTextarea value="#{bean.idText}" rows="#{bean.rowNrs}" cols="40" />
Yeah you can.., Have a look this example...
Bean Class:
private int rowValue;
//getters & setters for rowValue
//if you want column size as "50" then make rowValue is divided by 50.
this.rowValue = para.length()/50; //para is a string which would have database value
Now you have row value in back bean... just use this value as..
<h:inputTextarea id="para" value="#{beanName.idText}" rows="#{beanName.rowValue}" cols="50" />
Secondary Option..
By JavaScript:
You can try by using JavaScript like..
<script language="javascript">
function SetNewSize(textArea) {
if (textArea.value.length > 5) {
textArea.cols = 50;
textArea.rows = 50;
} else {
textArea.cols = 30;
textArea.rows = 20;
}
}
</script>
<textarea name="x" onKeyUp="SetNewSize(this);" cols="15" rows="10"></textarea>
Try similar way to implement this in your inputTextArea...
Related
I have few columns in the Data Table which displays the column name and row values dynamically.
But the first column in the data table have the values which has link. when we click that value it redirects to other screen.
Problem is when we export the csv/excel report. The first column which has this hyperlink not displaying the exact values. it shows as below in the excel
org.primefaces.component.column.Column#72d586ad - instead of exact value like "S123456789"
Please suggest how to display the exact value in the excel and csv.
<p:column headerText="#{msg['column.header']}" width="100" styleClass="columnLeft" filterBy="#{sampleDTO.linkNum}" sortBy="#{sampleDTO.linkNum}" id="linkNum">
<e:dataTableCommandLink id="viewTestLink" index="#{index}" value="#{sampleDTO.linkNum}" bean="#{sampleListBean}" action="viewLinkViewer"
ajax="false" currentDto="#{sampleDTO}"/>
</p:column>
Thanks in advance
Nithyn K
OK the reason its happening is because you are using a custom component <e:dataTableCommandLink which is why it can't figure out what text to display.
Here is what I would do use the ExportFunction...
Create a custom exporter my example uses CDI.
#Named
#ApplicationScoped
public class PassthroughColumnExporter {
public String export(final UIColumn column) {
String value = StringUtils.EMPTY;
for (final UIComponent child : column.getChildren()) {
final Object exportValue = child.getAttributes().get("data-export");
if (exportValue != null) {
value = String.valueOf(exportValue);
break;
}
}
return value;
}
}
In your XHTML use this custom exporter to export the value you want looking for the data-export attribute.
<p:column exportFunction="#{passthroughColumnExporter.export}">
<e:dataTableCommandLink value="#{row.displayValue}" data-export="#{row.exportValue}" />
</p:column>
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.
I need to keep filtered data when I navigate between pages. After entering data into a filter cell of a data table, it displays correct filtered rows. If last entered data in the filter cell doesn't match any data rows to display and when I navigate to another page and return back - column headers and filter cells are not rendered. There is only paginator are displayed. It works fine if last entered data in the filter cell matches some data rows. It work properly also if I don't leave the page with data table.
jsf code:
<p:dataTable id="tableId" var="intance" widgetVar="instance"
value="#{model.rows}" filteredValue="#{model.filteredRows}"
sortBy="#{model.sortBy}" sortMode="multiple" rows="5"
rowsPerPageTemplate="5, 15" paginator="true" paginatorPosition="bottom">
<p:ajax event="filter" listener="#{model.onFilter}"/>
<p:ajax event="sort" listener="#{model.onSort}"/>
<p:columns id="columnId" value="#{instance.columnsData}"
var="instanceColumn" columnIndexVar="ind" rendered="true"
sortBy="#{instance.columnsData[ind]}"
filterBy="#{instance.columnsData[ind]}" filterMatchMode="contains"
filterValue="#{model.tableFilters[''.concat(ind)]}"
headerText="#{labels[ind]}">
<h:outputText value="#{instance.columnsData[ind]}"/>
</p:columns>
</p:dataTable>
java code:
public class Model {
private List<MyRow> filteredRows;
private List<MyRow> rows;
private Map<String, String> tableFilters;
public void onFilter(FilterEvent event) {
tableFilters = event.getFilters();
if (MapUtils.isEmpty(tableFilters)) {
filteredRows = null;
}
}
public void List<MyRow> getRows() {
//retreve data from service and transform to List<MyRow>)
return rows;
}
/* getters and setter */
}
public class MyRow {
private List<Object> columnsData;
/* getters and setters */
}
Any thoughts? The code looks fine to me and should work. I use primefaces 3.5.
Thanks
The root of the problem is value="#{instance.columnsData}" of p:columns. Using #{instance} variable of the p:dataTable in this case is a mistake.
It works fine when page is loaded for a first time and when #{model.rows} is not empty.
When the #{model.rows} is not empty and when we type a value in the filter cell that doesn't match data in #{model.rows}, there is displayed no rows but column headers and filter cells are rendered anyway because of partial rendering only the data content (table headers and filter cells was rendered during rendering the page).
When we navigate to an another page and then return back to the page with our filtered rows in the data table, there is a new full rendering of the page. So in this case (#{model.filteredRows} is not null) it doesn't matter how much data #{model.rows} contain. #{model.filteredRows} will be used to render the data table content. So when primefaces renders data table, in my case there is no data to render at all because of #{model.filteredRows} is empty not null.
Because I use #{instance} variable of the p:dataTable in p:columns, p:columns will render no columns - no column headers and filter cells to display.
Solution: use separate field to contain columns info.
//edited class Model
public class Model {
//add a field that contains columns count. For example:
private List<Integer> columns = Collections.nCopies(5, 1);
//another fields
}
Need to use value="#{model.columns}" instead of value="#{instance.columnsData}"
<p:columns id="columnId" value="#{model.columns}"
var="instanceColumn" columnIndexVar="ind" rendered="true"
sortBy="#{instance.columnsData[ind]}"
filterBy="#{instance.columnsData[ind]}" filterMatchMode="contains"
filterValue="#{model.tableFilters[''.concat(ind)]}"
headerText="#{labels[ind]}">
<h:outputText value="#{instance.columnsData[ind]}"/>
</p:columns>
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..
I would like your comments and suggestion on this. I am doing the pagination for a page in jsf. The datatable is bound to a Backing Bean property through the "binding" attribute. I have 2 boolean variables to determine whether to render 'Prev' and 'Next' Button - which is displayed below the datatable. When either the 'Prev' or 'Next' button is clicked, In the backing bean I get the bound dataTable property and through which i get the "first" and "rows" attribute of the datatable and change accordingly. I display 5 rows in the page. Please comment and suggest if there any better ways. btw, I am not interested in any JSF Component libraries but stick to only core html render kit.
public String goNext()
{
UIData htdbl = getBrowseResultsHTMLDataTable1();
setShowPrev(true);
//set Rows "0" or "5"
if(getDisplayResults().size() - (htdbl.getFirst() +5)>5 )
{
htdbl.setRows(5);//display 5 rows
}else if (getDisplayResults().size() - (htdbl.getFirst() +5)<=5) {
htdbl.setRows(0);//display all rows (which are less than 5)
setShowNext(false);
}
//set First
htdbl.setFirst(htdbl.getFirst()+5);
return "success";
}
public String goPrev()
{
setShowNext(true);
UIData htdbl = getBrowseResultsHTMLDataTable1();
//set First
htdbl.setFirst(htdbl.getFirst()-5);
if(htdbl.getFirst()==0)
{
setShowPrev(false);
}
//set Rows - always display 5
htdbl.setRows(5);//display 5 rows
return "success";
}
Please comment and suggest if there any better ways.
Well, that gives not much to answer on. It's at least not the way "I" would do, if you're asking for that. Long story short: Effective datatable paging and sorting. You only need Tomahawk (face it, it has its advantages). But if you're already on JSF2+Facelets instead of JSF1+JSP, then you can in fact also use ui:repeat and #ViewScoped instead of t:dataList and t:saveState.
We can use 'Repeat' component - this is similar to dataList or dataTable component in Primefaces
<p:repeat id="repeatComponent" var="education" value="#{backingBean.educationList}" emptyMessage="No records found">
<h:panelGroup>
<p:outputLabel for="center" value="Education Center:" />
<br />
<h:panelGroup>
<h:outputText id="center" value="#{education.centerName}">
</h:outputText>
</h:panelGroup>
</h:panelGroup>
</p:repeat>
This is similar to for loop in java
var - this act as loop iterator
value - takes list object
emptyMessage - takes String value, will get displayed when passed list object is empty