Update form from another form using <f: ajax> in JSF - jsf

Good day,
I am developing an application in java server faces 2.2.20 and mariadb 10.4 databases.
I have a problem when updating with f: ajax to another form where I have a table that lists the products with their respective images entered, but the images returned by the method from the bean to the img in html are not displayed, although the image if it has in the src its respective route; The good content as text if it is updated correctly without reloading the page this means that if ajax works in part.
This is the code where the product data is entered and the image is uploaded to the controller.
<h:form id="crearCatalogos" enctype="multipart/form-data"> <!--prependId="false" -->
<div class="container">
<div class="row">
<div class="col-lg-5">
<fieldset>
<legend> Informacion:</legend>
<h:messages style="color:red"></h:messages>
<label>Nombre de categoria: </label><br/>
<h:inputText value="#{FileUploadFormBeanRequest.nombreCatalogo}" id="primerNombre" class="inputPersonalizado" html5:placeholder="Ingrese el nombre" maxlength="20" required="true" validatorMessage="No debe superar 20 caracteres" requiredMessage="Ingrese el nombre"></h:inputText><br/><br/>
<label>Seleccionar imagen: </label><br/>
<h:inputFile id="imgInp" value="#{FileUploadFormBeanRequest.archivoCarga}" validator="#{FileUploadFormBeanRequest.validarImagenCategoria}" class="inputPersonalizadoFile"> </h:inputFile>
<br/><br/>
<h:commandButton class="btn btn-primary" value="Cargar">
<f:ajax render="#form : formVerCatalogos : table_verCatalogos" event="action" execute="#form" listener="#{FileUploadFormBeanRequest.guardarDatosCategoria()}"></f:ajax>
</h:commandButton>
</fieldset>
<br/><br/>
</div>
<div class="col-lg-5 imgCategorias">
<div class="text-center">
<img id="noImagen54" src="../TEMPLATE/img/noImagen.jpeg" class="rounded img-thumbnail" alt="..."/>
<img id="imagenCategoriaFile" src="#" class="rounded img-thumbnail imagenCategoriaFile" alt="..."/>
</div>
</div>
</div>
</div> ​
</h:form>
first form view
second view with data
This is the code of the controller method that is called from the commandButton of the view, which is responsible for saving the data entered of the product and the respective image.
public void guardarDatosCategoria() {
this.archivoCarga = archivoCarga;
try (InputStream input = archivoCarga.getInputStream()) {
String fileName = archivoCarga.getSubmittedFileName();
Calendar hoy = Calendar.getInstance();
DateFormat formatter = new SimpleDateFormat("yyyyMMdd-hhmmss");
String[] ext = fileName.split("\\.");
fileName = ext[0] + formatter.format(hoy.getTime()) + "." + ext[1];
File directorio = new File(folder+"/"+this.nombreCatalogo);
if(!directorio.exists()){
if(directorio.mkdir()){
directorio.mkdir();
Files.copy(input, new File(directorio, fileName).toPath());
//System.out.println(directorio.getAbsolutePath());
}else{
System.out.println("Error al crear directorio");
}
}
//String salida = FacesContext.getCurrentInstance().getExternalContext().getApplicationContextPath();
//System.out.println(salida);
Catalogo objCatalogo = new Catalogo();
objCatalogo.setNombre(this.nombreCatalogo);
catalogoFacadeLocal.create(objCatalogo);
Imagen objImagen = new Imagen();
objImagen.setRuta("../Resources/img/Categorias/"+this.nombreCatalogo+"/"+fileName);
objImagen.setEstado("Principal");
objImagen.setIdCatalogo(objCatalogo);
imagenFacadeLocal.create(objImagen);
} catch (Exception e) {
e.printStackTrace();
}
this.archivoCarga=null;
this.nombreCatalogo="";
}
This is the view code that I need to reload using f: ajax de jsf
<!--VER CATEGORIAS -->
<div class="tab-pane fade active show" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab">
<h:form id="formVerCatalogos">
<table id="table_verCatalogos" class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">CATEGORIA</th>
<th scope="col">TIPO</th>
<th scope="col">IMAGEN</th>
</tr>
</thead>
<tbody>
<c:forEach items="#{FileUploadFormBeanRequest.listarImagenes()}" var="catalogoImg" varStatus="paso" rendered="#{!empty FileUploadFormBeanRequest.listarImagenes()}" >
<tr>
<th scope="row">#{paso.index+1}</th>
<td>#{catalogoImg.idCatalogo.nombre}</td>
<td>#{catalogoImg.estado}</td>
<td><h:graphicImage id="noImagen" value="#{catalogoImg.ruta}" class="rounded img-thumbnail img_ver_categorias"></h:graphicImage> </td>
</tr>
</c:forEach>
</tbody>
</table>
</h:form>
</div>
[enter image description here][3]
This is the code of the controller that is responsible for returning the data entered, to be displayed in the table that I need to reload.
public List<Imagen> listarImagenes(){
try {
return imagenFacadeLocal.findAll();
} catch (Exception e) {
return null;
}
}
This is how you look when the data entered is saved and the jsf ajax is executed, but the image cannot be visualized even if I look at the src of the img tag, the path is found. The only way to view the page is to reload the entire page arbitrarily, but it is not the idea.
in this view the text rendering is done, but the image is not displayed
Inspecting the element with f12, we can see that the img tag, if it has the correct path, but is not displayed with the JSF f: ajax.
I am very grateful that you give me a help, I have already searched, read, documented and the truth is that I cannot solve it on my own, I do not understand what it takes. Happy day thank you very much.
INSPECTING THE VIEW WITH F12, it is shown that the src attribute has the image path

Related

JSF couldn't pass data to bootsrtap modal

hello everyone i have a bootsfaces dataTabble, each row has an edit end delete action, i want to show a modal that contains selected row data to edit that object.
i successfully get the selected row i pass data to the managedBean, i assign data to managedProperties, but nothing is shown in Modal input elements.
this is my dataTable code:
<b:dataTable id="articleslist" value="#{listeArticlesAction.listeArticles}" var="article" page-length="10" paginated="true"
page-length-menu="10,20,30">
<b:dataTableColumn value="#{article.code}" label="Code" />
<b:dataTableColumn value="#{article.nom}" label="Nom" />
<b:dataTableColumn value="#{article.description}" label="Description" />
<b:dataTableColumn value="#{article.prix}" label="Prix (DH)" />
<b:dataTableColumn label="Modifier" style="text-align: center">
<h:commandButton style="padding: 0 4px;" iconAwesome="pencil" look="link" pt:data-target="#userEditModal" pt:data-toggle="modal"
action="#{listeArticlesAction.modifierArticle}">
<f:setPropertyActionListener target="#{listeArticlesAction.editArticle}" value="#{article}"
/>
<f:ajax render="#form"/>
</h:commandButton >
</b:dataTableColumn>
<b:dataTableColumn label="Supprimer" style="text-align: center">
<h:commandButton style="padding: 0 4px; text-align: center;" iconAwesome="trash" look="link" pt:data-target="#userEditModal" pt:data-toggle="modal"
onclick="confirmDelete()" action="#{listeArticlesAction.supprimerArticle}" >
<f:param name="actionDelete" value="article" />
</h:commandButton >
</b:dataTableColumn>
</b:dataTable>
and this is my managedBean class:
public class ListeArticlesAction {
private List<Article> listeArticles = new ArrayList<Article>();
private String editArticleNom;
private String editArticleDescription;
private int editArticlePrix;
private Article editArticle;
/**
* Methode pour preparer la liste des articles
*/
#PostConstruct
public void init() {
listeArticles = ServiceFactory.getArticleService().allArticles();
}
public List<Article> getListeArticles() {
return listeArticles;
}
public void setListeArticles(List<Article> listeArticles) {
this.listeArticles = listeArticles;
}
public String getEditArticleNom() {
return editArticleNom;
}
public void setEditArticleNom(String editArticleNom) {
this.editArticleNom = editArticleNom;
}
public String getEditArticleDescription() {
return editArticleDescription;
}
public void setEditArticleDescription(String editArticleDescription) {
this.editArticleDescription = editArticleDescription;
}
public int getEditArticlePrix() {
return editArticlePrix;
}
public void setEditArticlePrix(int editArticlePrix) {
this.editArticlePrix = editArticlePrix;
}
public Article getEditArticle() {
return editArticle;
}
public void setEditArticle(Article editArticle) {
this.editArticle = editArticle;
}
public void supprimerArticle() {
}
/**
* methode pour modifier un article quelconque
*/
public void modifierArticle() {
editArticleDescription = editArticle.getDescription();
editArticleNom = editArticle.getNom();
editArticlePrix = editArticle.getPrix();
}
}
and this is my modal html code:
<div class="modal" id="userEditModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">
Modifier le produit
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">
×
</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="edit_product_name" class="form-control-label">
Nom:
</label>
<h:inputText type="text" class="form-control" id="edit_product_name"
value="#{listeArticlesAction.editArticleNom}" autocomplete="off" />
</div>
<div class="form-group">
<label for="edit_product_description" class="form-control-label">
Description:
</label>
<h:inputTextarea class="form-control" id="edit_product_description"
value="#{listeArticlesAction.editArticleDescription}" autocomplete="off" />
</div>
<div class="form-group">
<label for="edit_product_price" class="form-control-label">
Prix(DH):
</label>
<h:inputText type="text" class="form-control m-input" id="edit_product_price"
value="#{listeArticlesAction.editArticlePrix}" autocomplete="off" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">
Annuler
</button>
<button type="button" class="btn btn-primary">
Modifier
</button>
</div>
</div>
</div>
</div>
Most likely you're updating the wrong part of the screen. That happens to many people using modals for the first time. Thing is, the modal is rendered when the page is loaded. That's potentially a minute before the button is clicked. So the modal doesn't know which data to display. You tell it using the update attribute of the command button.
As far as I can see, the datatable and the Java bean are OK. With the exception of the update region. Your code snippets don't show where the <h:form> or <b:form> tag is, so it's almost certainly outside the datatable. However, what you should update is the content of the modal. Don't update the entire modal (because that renders it hidden again). Just the content. Something like update="#(.modal-dialog)".
The modal itself looks a bit odd to me. What is listeArticlesAction? Judging from the other code snippets, you want to use listeArticlesAction.editArticle instead.
Side remark: I suggest you choose a language for the variable names (and stuff like this) and use it consistently. French is a good choice, although most developers (except me) recommend English. But it's hard enough to remember the variable name. You don't have to add the burden of remembering the language :).

'Check' not displayed on selected items from a p:selectManyMenu

I'm using the selectManyMenu widget from Primefaces 5.3 to display the list of roles users can have in each of our apps.
<p:outputLabel value="Roles:" rendered="#{controller.enabledApp[app.id] and not empty app.roles}"/>
<p:selectManyMenu converter="#{roleConverter}" var="r" filter="true" filterMatchMode="contains" showCheckbox="true"
rendered="#{controller.enabledApp[app.id] and not empty app.roles}" value="#{app.selectedRoles}">
<f:selectItems value="#{app.roles}" var="role" itemLabel="#{role.name}" itemValue="#{role}"/>
<p:column>
<h:outputText value="#{r.name}"/>
</p:column>
</p:selectManyMenu>
The problem is, when I preload these roles from the database, populating the selectedRoles field of the app entity, Primefaces adds the ui-state-highlight CSS class to the table rows used to represent these selected roles, but it doesn't add the ui-state-active to the div that represents the checkbox.
This is what I get:
<tr class="ui-selectlistbox-item ui-corner-all ui-state-highlight" style="">
<td>
<div class="ui-chkbox ui-widget">
<div class="ui-chkbox-box ui-widget ui-corner-all ui-state-default">
<span class="ui-chkbox-icon ui-icon ui-icon-check ui-c"/>
</div>
</div>
</td>
<td>Admin</td>
</tr>
And this is what I should get:
<tr class="ui-selectlistbox-item ui-corner-all ui-state-highlight" style="">
<td>
<div class="ui-chkbox ui-widget">
<div class="ui-chkbox-box ui-widget ui-corner-all ui-state-default ui-state-active">
<span class="ui-chkbox-icon ui-icon ui-c ui-icon-check"/>
</div>
</div>
</td>
<td>Admin</td>
</tr>
I could just change the CSS to display a checked checkbox when the parent tr has the ui-state-highlight class, but I'd much rather solve the problem.
Can this be a bug in Primefaces? Do I have some error that I'm not aware of?

java.lang.IllegalAccessException: Class javax.el.BeanELResolver can not access a member of class java.util.Arrays$ArrayList with modifiers "public"

I have such an p:selectManyCheckbox and it works ok:
<p:selectManyCheckbox id="groups" value="#{myBean.selectedGroups}">
<f:selectItems value="#{myBean.myGroups}" var="group" itemValue="#{group.id}" itemLabel="#{group.name}"/>
</p:selectManyCheckbox>
Now I have to convert it to the Tree component (adding Group parent to data), but my PrimeFaces version 3.4.1. doesn't support such a functionality. For better customization I decided to make this selectManyCheckbox manually with html and <ui:repeat>):
<div id="j_idt25groups" class="ui-scrollpanel ui-scrollpanel-native ui-widget ui-widget-content ui-corner-all" style="height: 200px;">
<table id="groups" class="ui-selectmanycheckbox ui-widget">
<tbody>
<ui:repeat value="#{myBean.myGroups}" var="group" varStatus="status">
<tr>
<td>
<div class="ui-chkbox ui-widget">
<div class="ui-helper-hidden-accessible">
<ui:fragment rendered="#{myBean.selectedGroups.contains(group.id)}">
<input id="groups:#{status.index}" name="groups" type="checkbox" value="#{group.id}"
checked="checked">
</input>
</ui:fragment>
<ui:fragment rendered="#{not myBean.selectedGroups.contains(group.id)}">
<input id="groups:#{status.index}" name="groups" type="checkbox" value="#{group.id}">
</input>
</ui:fragment>
</div>
<div class="ui-chkbox-box ui-widget ui-corner-all ui-state-default">
<span class="ui-chkbox-icon"></span>
</div>
</div>
</td>
<td>
<label for="groups:#{status.index}">#{group.name}</label>
</td>
</tr>
</ui:repeat>
</tbody>
</table>
</div>
Now i have a problem with this code #{prpBean.selectedGroups.contains(group.id)}:
java.lang.IllegalAccessException: Class javax.el.BeanELResolver can not access a member of class java.util.Arrays$ArrayList with modifiers "public"
Is it possible to solve this problem?
Does it exists an easier way to convert such a structure to the Tree?
The contains() method of java.util.Arrays$ArrayList is not immediately accessible by Java reflection. This could be a (corner case) bug in the EL implementation being used. It may work in a different EL implementation. It may be worth a bug report to the EL implementation vendor, but it is what it is.
When creating selectedGroups, use new ArrayList() instead of Arrays#asList() and all should be well.

Colorpicker doesn't work

i use Liferay 6.1, I created a portlet with code (Link: http://www.liferay.com/community/wiki/-/wiki/Main/Using+Lifery+provided+Color+Picker+in+Own+Portlets)
<script type="text/javascript"> jQuery( function() { var colorPicker = new Liferay.ColorPicker( { hasImage: true } ); } ); </script>
<tr> <td> <input class="text-input" id="color" name="color" size="9" type="text" value="" />
<img align="absmiddle" alt="<liferay-ui:message key="color" />" border="0" class="use-color-picker" height="18" hspace="0" src="<%= themeDisplay.getPathThemeImages() %>/color.png" title="<liferay-ui:message key="color" />" vspace="0" width="18" style="cursor: pointer;" />
</input> </td> </tr>
but it doesn't work, please help me :)
You need to pass more options to new Liferay.ColorPicker . According to the guide you posted:
Options:
•context (Object): A DOM object which specifies the context in which
to search for the item
•hasImage: (Boolean) If set to true, it uses
the "item" param or whatever image has the .use-color-picker class as
the image
•item: (Object|String): A DOM object or a jQuery Selector
string that specifies which field to insert the selected value into
•onChange (Function): A function that will get called whenever the
color changes
•onClose (Function): A function that will get called
when the color picker is closed.

People search in SharePoint using partial names

My employer is switching their internal portal over to SharePoint. One of the highly used features of the previous portal was a 'people search' that allowed partial names. SharePoint 2007 defaults to keyword searches which only match against the exact word(s) given as search terms. It can do full-text searches but you have to provide the property name, e.g. "FirstName:tom" (without the quotes of course). That works for a programmatic solution but not for end users.
Is there a way in SharePoint 2007 to let users search for people using partial names?
I found this solution that works well enough for us.
Add a ContentEditor web part to the target page and go to the HTML editor button. Add the following HTML code. It creates two input fields (firstname/lastname) and then creates a query with the search terms included as property searches which will invoke the full-text search.
Note: you need to replace the search result page with the appropriate location for your configuration.
<script language="javascript">
//function to handle enter on keyboard
function txtWildPeopleFinder_KeyDown(e)
{
if (e.keyCode == 13 || e.keyCode==10)
{
e.returnValue=false;
DoWildPeopleSearch();
return false;
}
else
return true;
}
//escape apostrophes in search strings
function escapestr(str)
{
return str.replace("'","%22");
}
//search function
function DoWildPeopleSearch()
{
var firstname = escapestr(document.all["firstname"].value);
var lastname = escapestr(document.all["lastname"].value);
var url;
//search on last name
if(firstname == "")
{
url = "/searchcenter/Pages/peopleresults.aspx?k=LastName%3A" + lastname;
window.location=url;
return;
}
//search on first name
if(lastname == "")
{
url = "/searchcenter/Pages/peopleresults.aspx?k=FirstName%3A" + firstname;
window.location=url;
return;
}
//first and last
url = "/searchcenter/Pages/peopleresults.aspx?k=lastname%3A" + lastname + "%20FirstName%3A" + firstname;
window.location=url;
return;
}
</script>
<table cellpadding="2" cellspacing="0" border="0" width="100%" ID="Table3">
<tr>
<td width="80" nowrap>
First Name:
</td>
<td width="100%">
<input size="20" maxlength="100" id="firstname" name="firstname" type="text" onkeydown="txtWildPeopleFinder_KeyDown(event)">
</td>
</tr>
<tr>
<td width="80" nowrap>
Last Name:
</td>
<td>
<input size="20" maxlength="100" id="lastname" name="lastname" type="text" onkeydown="txtWildPeopleFinder_KeyDown(event)">
</td>
</tr>
<tr>
<td> </td>
<td>
<input type="button" onclick="DoWildPeopleSearch()" value="Search">
</td>
</tr>
</table>

Resources