I'm trying to print out a string as a list in a Razor Page. I have the following:
Aboud.cshtml.cs:
public void OnGet()
{
Message = "Hello";
Message = AddToMessage(new string[] {
"This is my first page",
"By the end of this course",
"I will be a Razor Pages Pro!"});
}
private string AddToMessage(string[] text)
{
string result = "";
foreach (string txt in text)
{
result += txt + "\n";
}
result = ReplaceToUpper(result);
return result;
}
private string ReplaceToUpper(string text)
{
return text.ToUpper();
}
About.cshtml:
#page
#model AboutModel
#{
}
<h1>This is the about page!</h1>
<br />
<p>#{
string[] message = #Model.Message.Split("/n");
foreach(string text in message)
{
<br /><p>#text</p>;
}
}
</p>
The page keeps printing out the line in one string. I've also tried using an unordered/ordered list as the HTML markup and I'm not able to make it work.
Need other backslash so \n instead of /n
#page
#model AboutModel
#{
}
<h1>This is the about page!</h1>
<br />
<p>#{
string[] message = #Model.Message.Split("\n");
foreach(string text in message)
{
<br /><p>#text</p>;
}
}
</p>
I have two , when there is a change in the selected option in the first select it must fire up an update in the second Select but it is only happening with page load.
Cliente.xhtml
<h:selectOneMenu id="ListaProvincia" immediate="true" value="#{beanCliente.provincia}">
<f:selectItems id="itemProvincia" value="#{beanCliente.listaProvincia}"/>
<f:ajax listener="beanCliente.changeCanton()" render="Canton" />
</h:selectOneMenu>
<h:outputLabel styleClass="optional">Canton</h:outputLabel>
<h:selectOneMenu id="Canton" value="#{beanCliente.canton}">
<f:selectItems value="#{beanCliente.listaCantones}"/>
</h:selectOneMenu>
beanCliente
public LinkedList getListaCantones() {
return this.listaCantones;
}
public void setDistrito(int Distrito) {
this.Distrito = Distrito;
}
public int getDistrito() {
return Distrito;
}
public void setListaDistrito()throws SNMPExceptions, SQLException {
String nombre="";
int id_distrito=0;
DistritoDB objDB = new DistritoDB();
LinkedList resultList = new LinkedList();
for (Iterator iter = objDB.listaDistritos(this.getCanton()).iterator(); iter.hasNext();) {
Distrito di = (Distrito) iter.next();
id_distrito= di.getID_Distrito();
nombre=di.getNombre();
resultList.add(new SelectItem(id_distrito, nombre));
}
this.listaCantones = resultList;
}
i have a String like "Hello [everyone]!". "Everyone" should be replaced with a commandLink that points to an Page-Object.
For Example:
My Code detects "[everyone]" and creates a new "Page" with the headline "everyone" in my JavaDB Database. Now i want that [everyone] will shown as an commandLink:
Hello <h:commandLink value="everyone" action="#{PageController.getPage(everyone)}" />
or something else.
ATM i have this code to display the text with the []-Tags:
<h:outputText value="#{PageController.currentPage.latestContent.text}" />
Now what is the best practise to replace Tags (i.e. [XYZ]) with a specific commandLink? Or rather: how i can replace substrings with JSF-Tags (they should be rendered)? I have only found the possibility to create converter, but only examples to convert the complete string. :/ To find out the right substring i use Regulary Expressions.
Merry Christmas :)
My Soluion:
#ApplicationScoped
#Named("TagViewPhase")
public class TagViewPhase implements Serializable {
Application app;
public void beforePhase(PhaseEvent event) {
if (app == null) {
app = event.getFacesContext().getApplication();
}
if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
scanForPageContent(event.getFacesContext().getViewRoot());
}
}
private void scanForPageContent(UIComponent component) {
for (UIComponent i : component.getChildren()) {
if ("pageContent".equals(i.getId())) {
HtmlOutputText content = (HtmlOutputText) i;
HtmlPanelGroup group = generatePageContent(content);
content.getParent().getChildren().add(group);
content.getParent().getChildren().remove(i);
} else {
scanForPageContent(i);
}
}
}
private HtmlPanelGroup generatePageContent(final HtmlOutputText pContent) {
List<UIComponent> childTree = new ArrayList<>();
String content = pContent.getValue().toString();
Pattern pattern = Pattern.compile("\\[(.*?)\\]");
Matcher matcher = pattern.matcher(content);
Integer start, end = 0;
String linkValue;
while (matcher.find()) {
start = matcher.start();
if (end < start) {
HtmlOutputText htmlText = (HtmlOutputText) app.createComponent(HtmlOutputText.COMPONENT_TYPE);
htmlText.setValue(content.substring(end, start));
childTree.add(htmlText);
}
end = matcher.end();
linkValue = content.substring(start + 1, end - 1);
HtmlCommandLink link = (HtmlCommandLink) app.createComponent(HtmlCommandLink.COMPONENT_TYPE);
link.setValue(linkValue);
link.setActionExpression(JSFExpression.createMethodExpression(
"#{PageController.switchPageByString('" + linkValue + "')}",
String.class,
new Class<?>[]{}
));
childTree.add(link);
}
if (end < content.length()) {
HtmlOutputText htmlText = (HtmlOutputText) app.createComponent(HtmlOutputText.COMPONENT_TYPE);
htmlText.setValue(content.substring(end, content.length()));
childTree.add(htmlText);
}
HtmlPanelGroup group = (HtmlPanelGroup) app.createComponent(HtmlPanelGroup.COMPONENT_TYPE);
group.getChildren().addAll(childTree);
return group;
}
}
xhtml File:
<f:view beforePhase="#{TagViewPhase.beforePhase}">
<h:panelGroup>
<h:outputText id="pageContent" value="#{PageController.currentPageContent.text}" />
</h:panelGroup>
</f:view>
I have an implementation of lazyDataModel following this tutorial http://uaihebert.com/?p=1120
My code its a bit different from this tutorial, here it is:
View:
<p:dataTable id="tablaClientes" value="#{AgendaManualMBean.allClientes}"
var="tablaClientes"
widgetVar="clienteTable"
rowKey="#{tablaClientes.clDocid}"
selection="#{AgendaManualMBean.ciatt001}" selectionMode="single" rows="10"
lazy="true" paginatorPosition="top"
paginatorTemplate="{RowsPerPageDropdown}{FirstPageLink}{PreviousPageLink}
{CurrentPageReport} {NextPageLink} {LastPageLink}" rowsPerPageTemplate="5,10,15"
emptyMessage="No existen clientes">
<f:facet name="header" >
<p:outputPanel>
<h:outputText value="Busqueda " />
<p:inputText id="globalFilter" onkeyup="clienteTable.filter()"
style="width:150px" size="10"/>
</p:outputPanel>
</f:facet>
<p:column id="numOrdenColumn" filterBy="#{tablaClientes.clDocid}"
width="50"
headerText="Identificación"
filterMatchMode="contains">
<h:outputText value="#{tablaClientes.clDocid}" />
</p:column>
<p:column id="nomCliColumn"
filterBy="#{tablaClientes.clNombre1}"
width="250"
headerText="Cliente"
filterMatchMode="contains">
<h:outputText value="#{tablaClientes.clNombre1}" />
</p:column>
</p:dataTable>
MY Managed Bean:
public LazyDataModel<Ciatt001> getAllClientes() {
if (listaClientesLazy == null) {
listaClientesLazy = new LazyClienteModel(ambiente.getCodCia(),ambiente.getCodAge());
//listaClientesLazy = new LazyClienteModelMBean();
}
return listaClientesLazy;
}
My LazyDataModel
public List<Ciatt001> load(int startingAt, int maxPerPage, String sortField, SortOrder sortOrder, Map<String, String> filters) {
String a = "";
try {
listaClientes = new ArrayList<Ciatt001>();
a = String.valueOf(agendamientoSession.countClientes2(cia, age));
listaClientes = agendamientoSession.listaClientes2(cia, age, startingAt, maxPerPage);
} catch (Exception e) {
e.printStackTrace();
}
if (getRowCount() <= 0) {
setRowCount(Integer.parseInt(a));
}
setPageSize(maxPerPage);
return listaClientes;
}
#Override
public Object getRowKey(Ciatt001 ciatt001) {
return ciatt001.getClDocid();
}
#Override
public Ciatt001 getRowData(String docid) {
//Integer id = Integer.valueOf(idBandeja);
for (Ciatt001 ciatt001 : listaClientes) {
if (docid.equals(ciatt001.getClDocid())) {
return ciatt001;
}
}
return null;
}
And the ejb methods:
public List<Ciatt001> listaClientes2(String cia, String age ,int startingAt, int maxPerPage) {
Query query = em.createNamedQuery("Ciatt001.listaClientesPorCiaPorAge2");
query.setParameter(1, cia);
query.setParameter(2, age);
query.setFirstResult(startingAt);
query.setMaxResults(maxPerPage);
return query.getResultList();
}
public String countClientes2(String cia, String age) {
Query query = em.createNamedQuery("Ciatt001.countClientes2");
query.setParameter(1, cia);
query.setParameter(2, age);
return query.getSingleResult().toString();
}
How can I achieve a global filter using this lazy loading implementation?
On load functon, get the filter value (check if is not null).
String filterValue = filters.get("globalFilter");
Then if you are not using any others filters ,make a query using disjunction (OR):
"select * from table where x = ? OR y = ?" //replace ? for globalFilter value
If you are using others fields, you should do:
//normal filters
filtersCondition = "(x = ? AND y = ?)" //replace ? for filters values
//global filters
globalFilterCondition = "(x = globalFilter OR y = globalFilter)" //replace ? for globalFilter value
//normal filters + global filter
query = "select * from table where " +filtersCondition+ " AND "+ globalFilterCondition
Of course, this queries are just an example , you should build a nice one and well parameterized =)
This how i get it to work , pagination and filtering :D
The LazyDataModel look like this now:
in the load method:
Set set = filters.entrySet();
Iterator i = set.iterator();
if (i.hasNext()) {
Map.Entry me = (Map.Entry) i.next();
filterValue = (String) me.getValue();
}
a = String.valueOf(agendamientoSession.countClientes2(cia, age, filterValue));
listaClientes = agendamientoSession.listaClientes2(cia, age, startingAt, maxPerPage, filterValue);
setRowCount(Integer.parseInt(a));
the ejb :
public List<Ciatt001> listaClientes2(String cia, String age ,int startingAt, int maxPerPage,String filtro) {
Query query = em.createNamedQuery("Ciatt001.listaClientesPorCiaPorAge2");
query.setParameter(1, cia);
query.setParameter(2, age);
query.setParameter(3,"%"+filtro+"%");
query.setParameter(4,"%"+filtro+"%");
query.setFirstResult(startingAt);
query.setMaxResults(maxPerPage);
}
and my query:
select * from ciatt001 c where c.cl_co_cia=? and c.cl_ag_agencia =?
and c.cl_estado='A' and (c.cl_docid like ? or c.cl_nombre1 like ? .. more filters if needed)
thats all,
now wil be looking for the sort implementation :D
I have multiple selectInputText controls inside a datatable, something like this:
<ice:dataTable id="attributesList" value="#{myForm.myAttributes}" var="entry" cellpadding="0" rows="9999" columnClasses="myColumn,myColumn">
<ice:column>
<!-- auto-complete -->
<ice:panelGroup>
<ice:selectInputText rows="15" width="120" maxlength="255" value="#{entry.attribute.stringValue}" valueChangeListener="#{myFieldAutocomplete.updateList}" immediate="true">
<f:selectItems value="#{myFieldAutocomplete.list}" />
<f:attribute name="fieldName" value="#{entry.name}" />
</ice:selectInputText>
</ice:panelGroup>
</ice:column>
</ice:dataTable>
My backing bean code is this:
public class myFieldAutocomplete {
// default value, empty string
private String currentFieldValue = "";
// list of possible matches.
private List<SelectItem> matchesSIList = new ArrayList<SelectItem>();
public void updateList(ValueChangeEvent event) {
currentFieldValue = "";
// get a new list of matches.
setMatches(event);
if (event.getComponent() instanceof SelectInputText) {
SelectInputText autoComplete = (SelectInputText) event.getComponent();
if (autoComplete.getSelectedItem() != null) {
currentFieldValue = (String) autoComplete.getSelectedItem().getValue();
}
else {
String tempValue = getMatch(autoComplete.getValue().toString());
if(tempValue != null) {
currentFieldValue = tempValue;
}
}
}
}
public String getCurrentFieldValue() {
return currentFieldValue;
}
public List<SelectItem> getList() {
return matchesSIList;
}
private String getMatch(String value) {
String result = null;
if (matchesSIList != null) {
String str;
Iterator<SelectItem> itr = matchesSIList.iterator();
while (itr.hasNext()) {
SelectItem si = (SelectItem) itr.next();
str = (String) si.getValue();
if (str.startsWith(value)) {
result = str;
break;
}
}
}
return result;
}
public void setMatches(ValueChangeEvent event) {
List<String> newMatchesStrList = new ArrayList<String>();
if (event.getComponent() instanceof SelectInputText) {
SelectInputText autoComplete = (SelectInputText) event.getComponent();
myClassDAO myDao = (myClassDAO) Context.getInstance().getBean(myClassDAO.class);
String fieldName = (String) autoComplete.getAttributes().get("fieldName");
newMatchesStrList = myDao.findTemplateFieldValues((String)autoComplete.getValue(), fieldName);
}
// assign new matchList
if (this.matchesSIList != null) {
this.matchesSIList.clear();
}
Iterator<String> itr = newMatchesStrList.iterator();
while(itr.hasNext()) {
String str = (String) itr.next();
matchesSIList.add(new SelectItem(str, str));
}
}
}
The bean is in request scope (although I also tried with session scope). I am using ICEfaces community edition 1.8.2.
The problem is, these auto-complete controls are created dynamically based on certain attributes of each entry in the datatable. So, you can have, for example 2 or more such auto-complete controls in the same panelGroup. When this is the case, when you start typing something the first control, it seems to be triggering the event for all sibling auto-complete controls, and in the end returns the list for the last in order.
In general, I noticed erratic behavior caused by the fact that the event is triggered for all auto-complete controls at once, and values/lists get confused.
What am I doing wrong?
Thanks in advance!