BootsFaces-OSP icon indicating copy to clipboard operation
BootsFaces-OSP copied to clipboard

How to use AJAX with b:datatable (originally: The FacesMessages are not shown when are called from a row of a datatable)

Open mmncd opened this issue 6 years ago • 16 comments

I have a Datatable with a list of items and with each item I have a column with a button that if you click it, this item will be deleted if possible, if not it will throw a FacesMessages, but the FacesMessage is not shown, although in the JSF page there is the growl component.

mmncd avatar Jul 04 '18 08:07 mmncd

could you provide a short code example showing relevant portions of your xhtml and backing bean?

chongma avatar Jul 04 '18 09:07 chongma

Portion of the xhtml:

    <b:row styleClass="table-responsive">
        <b:dataTable id="cars" var="car" value="#{carsView.cars}" searching="false" 
excel="true" csv="true" pdf="true" columnVisibility="true" copy="true" print="true" 
multi-column-search='true' multi-column-search-position='top' searchable='false' 
page-length="5" page-length-menu="5,10,20">                    
            <b:dataTableColumn label="Brand">
                <h:outputText value="#{car.brand}"/>
            </b:dataTableColumn>
            <b:dataTableColumn value="#{car.number}" label="Number Plate">
            </b:dataTableColumn>
            <b:dataTableColumn label="Comments">
                <h:outputText value="#{car.comments}"  />
            </b:dataTableColumn>
            <b:dataTableColumn label="Borrar">
                <center><b:commandButton update="@form" look="danger" 
onclick="ajax:carsView.deleteCar(car)" class="fa fa-remove fa-lg" /></center>
            </b:dataTableColumn>
        </b:dataTable>
     </b:row>
    <b:row>
        <b:growl id="growl" globalOnly="true" showDetail="true" 
severity="info,warn, error, fatal"/>
     </b:row> 
 </h:form>

Portion of the backing bean:

public void deleteCar(Car car) {
	carRepository.delete(car);
	cars.remove(car);
        FacesMessages.info("Info", "The car has been deleted");
}

mmncd avatar Jul 04 '18 09:07 mmncd

is the row deleted? have you tried adding a faces message using this method:

FacesContext.getCurrentInstance().addMessage(null, 
    new FacesMessage(FacesMessage.SEVERITY_INFO, 
        "The car has been deleted", null));

i note that your growl is set for global only although i am not sure if that makes any difference

chongma avatar Jul 04 '18 15:07 chongma

@chongma "global only" should be OK, because the FacesMessage doesn't bear an id.

stephanrauh avatar Jul 05 '18 06:07 stephanrauh

Yes, the row is deleted. I have tried your suggestion, but it continues not showing the message. Maybe the fact that in the same view there are models avoids to see the message.

mmncd avatar Jul 06 '18 06:07 mmncd

could you post the full xhtml form? it is possible the b:growl is not positioned correctly in the form. maybe create a simple test form where a simple command button generates a FacesMessage. e.g. XHTML

<h:form>
<b:growl/>
<b:commandButton value="test" action="#{myBean.test}">
<f:ajax render="@form"/>
</b:commandButton>
</h:form> 

backing bean

public String test() {
FacesContext.getCurrentInstance().addMessage(null, 
    new FacesMessage(FacesMessage.SEVERITY_INFO, 
        "Testing growl", null));
}

chongma avatar Jul 06 '18 08:07 chongma

The full xhtml form is the following:

	<h:form>
	<b:row styleClass="placeholders">
			<p:fileUpload fileUploadListener="#{carsView.handleFileUpload}" mode="advanced"
							 update="messages" auto="true" allowTypes="/(\.|\/)(xlsm|xls|xlsx)$/" label="Import Excel of Cars">
			</p:fileUpload>
			<p:growl id="messages" showDetail="true" />
	</b:row>

	<b:modal id="amodal1" title="Contacts of #{carsView.selectedCar.id}" styleClass="modalPseudoClass1" closable="false"  close-on-escape="false" backdrop="false">
			<b:dataTable id="contacts" var="contact" value="#{carsView.selectedCar.contacts}" class="editableContactoTable" responsive="true" widgetVar="tableWidgetVar" scroll-horizontally="true">                    
				<b:dataTableColumn label="Main Contact">
					<h:outputText value="#{contact.fullName}"/>
				</b:dataTableColumn>
				<b:dataTableColumn label="Telephone Number">
					<h:outputText value="#{contact.telephone}" />
				</b:dataTableColumn>
			</b:dataTable>
			<f:facet name="footer">
			  <b:button value="Cerrar" dismiss="modal"/>
			</f:facet>
		</b:modal>

	<b:row styleClass="table-responsive">
		<b:dataTable id="cars" var="car" value="#{carsView.cars}" searching="false" 
			excel="true" csv="true" pdf="true" columnVisibility="true" copy="true" print="true" 
			multi-column-search='true' multi-column-search-position='top' searchable='false' 
			page-length="5" page-length-menu="5,10,20">                    
						<b:dataTableColumn label="Brand">
							<h:outputText value="#{car.brand}"/>
						</b:dataTableColumn>
						<b:dataTableColumn value="#{car.number}" label="Number Plate">
						</b:dataTableColumn>
						<b:dataTableColumn label="Comments">
							<h:outputText value="#{car.comments}"  />
						</b:dataTableColumn>
						<b:dataTableColumn label="Contacts" searchable="false">
						  <center><b:commandButton update="@form" look="info" oncomplete="$('.modalPseudoClass1').modal()" onclick="ajax:carsView.onclickCar(car)" class="fa fa-table fa-lg"/></center>
						</b:dataTableColumn>
						<b:dataTableColumn label="Delete">
							<center>
								<b:growl/>
								<b:commandButton look="danger" action="#{carsView.test}" class="fa fa-remove fa-lg">
									<f:ajax render="@form"/>
								</b:commandButton>
							</center>
						</b:dataTableColumn>
					</b:dataTable>
		<b:commandButton update="@form" col-sm="2" look="info" onclick="ajax:carsView.addCar()" class="fa fa-plus fa-lg" />
	</b:row>  
	</h:form>

mmncd avatar Jul 09 '18 08:07 mmncd

your b:growl component is in the loop of the b:dataTable so i imagine the html will create multiple growl components. try moving it to just below the h:form declaration

chongma avatar Jul 09 '18 14:07 chongma

also i note you have a p:growl and a b:growl. you should only need one?

chongma avatar Jul 09 '18 14:07 chongma

I have edited the xhtml form, and now I can see the messages. But, I continue with two problems: 1.- When an Ajax event occurs the searching and pagination of the database dissapear. 2.- The searching of the columns does not work. I copy my xhtml form:

	<p:messages id="messages"/>
	<h:form>
	<b:row styleClass="placeholders">
			<p:fileUpload fileUploadListener="#{carsView.handleFileUpload}" mode="advanced"
							 update="messages @(.editableCarTable)" auto="true" allowTypes="/(\.|\/)(xlsm|xls|xlsx)$/" label="Import Excel of Cars">
			</p:fileUpload>
	</b:row>
	
	<b:modal id="amodal1" title="Contacts of #{carsView.selectedCar.id}" styleClass="modalPseudoClass1" closable="false"  close-on-escape="false" backdrop="false">
			<b:dataTable id="contacts" var="contact" value="#{carsView.selectedCar.contacts}" class="editableContactoTable" responsive="true" widgetVar="tableWidgetVar" scroll-horizontally="true">                    
				<b:dataTableColumn label="Main Contact">
					<h:outputText value="#{contact.fullName}"/>
				</b:dataTableColumn>
				<b:dataTableColumn label="Telephone Number">
					<h:outputText value="#{contact.telephone}" />
				</b:dataTableColumn>
			</b:dataTable>
			<f:facet name="footer">
			  <b:button value="Cerrar" dismiss="modal"/>
			</f:facet>
		</b:modal>
	
	<b:row styleClass="table-responsive">
		<b:dataTable id="cars" var="car" value="#{carsView.cars}" searching="true" 
			excel="true" csv="true" pdf="true" columnVisibility="true" copy="true" print="true" 
			multi-column-search='true' multi-column-search-position='top' searchable='false' 
			searchable='false' page-length="5" page-length-menu="5,10,20" class="editableCarTable">                    
						<b:dataTableColumn label="Brand">
							<h:outputText value="#{car.brand}"/>
						</b:dataTableColumn>
						<b:dataTableColumn value="#{car.number}" label="Number Plate">
						</b:dataTableColumn>
						<b:dataTableColumn label="Comments">
							<h:outputText value="#{car.comments}"  />
						</b:dataTableColumn>
						<b:dataTableColumn label="Contacts" searchable="false">
						  <center><b:commandButton update="@form" look="info" oncomplete="$('.modalPseudoClass1').modal()" onclick="ajax:carsView.onclickCar(car)" class="fa fa-table fa-lg"/></center>
						</b:dataTableColumn>
						<b:dataTableColumn label="Delete" searchable="false">
							<center>
								<b:commandButton look="danger" action="#{carsView.test}" class="fa fa-remove fa-lg">
									<f:ajax render="@form"/>
								</b:commandButton>
								<b:commandButton update="messages @(.editableCarTable)" look="danger" onclick="ajax:carsView.deleteCar(car)" class="fa fa-remove fa-lg" />
							</center>
						</b:dataTableColumn>
					</b:dataTable>
		<b:commandButton update="@form" col-sm="2" look="info" onclick="ajax:carsView.addCar()" class="fa fa-plus fa-lg" />
	</b:row>  
	</h:form>

mmncd avatar Jul 10 '18 15:07 mmncd

  1. p:messages is outside the form. it should be inside the form to report messages which are relevant to the form
  2. normally i would place a b:modal outside the form
  3. you are updating multiple elements eg update="messages @(.editableCarTable)" whereas i would advise updating the whole form update="@form" at least until you know what you are doing (i normally only update the form as it is a headache to update small elements). this is a personal choice...
  4. some of your b:commandButton elements might not use ajax? ajax="true" or <f:ajax render="@form" />

chongma avatar Jul 10 '18 15:07 chongma

I implement the recommendations you gave me, but it continues dissapearing the searching and pagination of the datatable, and the searching of the columns does not work neither.

mmncd avatar Jul 10 '18 16:07 mmncd

You will need to provide a working example project which reproduces the problem otherwise it will be difficult for us to pinpoint the problem. You could use a maven archetype as a starting point

chongma avatar Jul 10 '18 16:07 chongma

@mmncd If your AJAX request replaces the entire table, you have to destroy and re-initialize it. Have a look at the documentation of the AJAX behaviour of the datatable.

stephanrauh avatar Jul 10 '18 18:07 stephanrauh

With the destroy table method, the database remains with the researching, but not with the pagination. Moreover, it is not updated with the deleted row. As opposed to without this method that at least the deleted row is not displayed.

<h:form  id="form">
.
.
.
<b:commandButton ajax="true" update="messages @(.editableCarTable)" 
                                  look="danger"
                                  onclick="formCarsWidget.DataTable().destroy();ajax:carsView.deleteCar(car)" 
                                  class="fa fa-remove fa-lg" />

mmncd avatar Jul 12 '18 09:07 mmncd

@mmncd Sorry for the long pause. Did you find a solution in the meantime? Or do you still need assistance?

As far as I understand,

  • you've managed to solve the bug you originally reported,
  • but the datatable still doesn't work as you expect it to do. In particular,
  • it's not updated after deleting the row (i.e. you delete a row, but it's still visible after the AJAX request),
  • and the paginator is lost after the AJAX request.

On the plus side, the "search" input field is there, and it keeps working even after the AJAX request.

Did I summary the current state of the art correctly?

stephanrauh avatar Jul 26 '18 21:07 stephanrauh

I'm afraid development of BootsFaces has slowed down considerably. We'll never manage to address this issue. Let's close it.

stephanrauh avatar Aug 12 '24 15:08 stephanrauh