У меня есть форма InputTextarea, в которой я могу сохранить введенные данные,
Также имеется таблица данных, где мы можем увидеть сохраненные данные, и Действия - Редактировать и удалить содержимое.
The функция сохранения работает нормально .
У меня есть две проблемы
Существующие проблемы / Вывод
Удалить
При попытке удалить комментарий кнопка удаления Не работает с первой попытки,
Работает, когда я обновляю sh всю страницу в браузере и затем нажимаю кнопку удаления. выбранный комментарий удаляется
Редактировать
Когда вы нажимаете кнопку редактирования, выбранный комментарий появляется / отображается в inputTextarea. После внесения необходимых изменений в комментарий и когда я пытаюсь сохранить его, он сохраняется как новая строка вместо обновления существующей строки.
Ajax Новый объект, созданный при попытке изменить существующий комментарий.
Фактический / ожидаемый результат
- После нажатия кнопки удаления комментарий должен быть удален
После нажатия кнопки редактирования комментарий отображается в области ввода текста, и та же запись должна быть обновлена.
Parent.x html
<h:form id="assesmentGameApplication" enctype="multipart/form-data" >
<h:panelGroup id="id2">
<p:tabView id="assesmentGameMain">
<p:tab id="assesmentGameFinal"
title="Assesment">
<ui:include src="/jsf/assesmentComments.xhtml" />
</p:tab>
</p:tabView>
</h:panelGroup>
</h:form>
assesmentComments.xhtml
<p:fieldset toggleable="true" toggleSpeed="500" legend="Comments">
<div id="assesmentComments" class="ui-fluid">
<div class="ui-g">
<div class="ui-g-12"><p:messages for="assesmentCommentsMessageId" showDetail="true" closable="false"><p:autoUpdate/></p:messages></div>
<div class="ui-g-1"></div>
<div class="ui-g-1"><p:outputLabel value="New Comments" rendered="true" /></div>
<div class="ui-g-8">
<p:row>
<p:inputTextarea rows="5" cols="200" counter="assesmentCommentsText" id="assesmentComments"
value="#{gamerCommentsMB.gameCommentsEntity.commentText}" maxlength="1000"
counterTemplate="{0} characters remaining." autoResize="false" validatorMessage="Too long, please limit to 10000 characters"
rendered="true" >
<f:validateLength maximum="10000" minimum="0" />
</p:inputTextarea>
<h:outputText id="assesmentCommentsText" />
</p:row>
</div>
<div class="ui-g-2"></div>
<div class="ui-g-2"></div>
<div class="ui-g-1">
<p:commandButton id="saveCommentButton" value="Save Comment" type="button"
onclick="PF('waitSpinner').show()" oncomplete="PF('waitSpinner').hide()"
widgetVar="saveCommentButtonVar" rendered="true" >
<p:ajax listener="#{gamerCommentsMB.saveNewComment}" process="@this assesmentComments" update="assesmentCommentsTable saveCommentButton assesmentComments" oncomplete="PF('waitSpinner').hide()"/>
</p:commandButton>
</div>
<div class="ui-g-9"></div>
</div>
<ui:include src="assesmentCommentsDetail.xhtml" />
assesmentCommentsDetail.x html
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
>
<div id="assesmentCommentsDetailsScreen" class="ui-fluid">
<p:spacer width="10" height="10" />
<h:panelGrid width="90%">
<p:dataTable id="assesmentCommentsTable"
value="#{gamerCommentsMB.gameCommentsList}"
var="assesmentCommentsRow" rows="10" widgetVar="assesmentCommentsTableVar"
selectionMode="single"
selection="#{gamerCommentsMB.selectGameComments}"
rowKey="#{assesmentCommentsRow.commentId}"
emptyMessage="No Comments found."
rowIndexVar="commentIterator">
<p:column style="text-align: center;"
headerText="Comment Text" >
<h:outputText value="#{assesmentCommentsRow.commentText}" >
</h:outputText>
<f:attribute name="rowId" value="#{commentIterator}" />
</p:column>
<p:column style="text-align: center; width:5%"
headerText="Actions" >
<p:commandButton id="fileEditCommentButton" icon="ui-icon-pencil" type="button" title="Click to Edit the comment"
onclick="PF('assesmentCommentsTableVar').unselectAllRows();"
onkeypress="PF('assesmentCommentsTableVar').unselectAllRows();"
update="assesmentCommentsDetailsScreen">
<p:ajax listener="#{gamerCommentsMB.editSelectedComment}" update=":assesmentGameApplication:assesmentGameMain:assesmentComments"/>
<f:attribute name="rowId" value="#{commentIterator}" />
</p:commandButton>
<p:commandButton id="fileCommentsDeleteButton" icon="ui-icon-trash" type="button" title="Click to Delete the comment"
onclick="PF('assesmentCommentsTableVar').unselectAllRows();"
onkeypress="PF('assesmentCommentsTableVar').unselectAllRows();"
update="assesmentCommentsDetailsScreen">
<p:ajax listener="#{gamerCommentsMB.deleteSelectedCommentConfirmation}" />
<f:attribute name="rowId" value="#{commentIterator}" />
</p:commandButton>
</p:column>
</p:dataTable>
</h:panelGrid>
Java Боб
@ManagedBean(name="gamerCommentsMB")
@ViewScoped
public class GamerCommentsMB implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(GamerCommentsMB.class);
private GameApplication gameApplicationEntity;
public GameApplication getGameApplicationEntity() {
return gameApplicationEntity;
}
public void setGameApplicationEntity(GameApplication gameApplicationEntity) {
this.gameApplicationEntity = gameApplicationEntity;
}
private Comments gameCommentsEntity;
public Comments getGameCommentsEntity() {
return gameCommentsEntity;
}
public void setGameCommentsEntity(Comments gameCommentsEntity) {
this.gameCommentsEntity = gameCommentsEntity;
}
private List<Comments> gameCommentsList;
public List<Comments> getGameCommentsList() {
return gameCommentsList;
}
public void setGameCommentsList(List<Comments> gameCommentsList) {
this.gameCommentsList = gameCommentsList;
}
private Date maxDate = new Date();
private boolean newCommentNotReady = true;
public boolean isNewCommentNotReady() {
return newCommentNotReady;
}
public void setNewCommentNotReady(boolean newCommentNotReady) {
this.newCommentNotReady = newCommentNotReady;
}
private Integer deleteCommentId;
public Integer getDeleteCommentId() {
return deleteCommentId;
}
public void setDeleteCommentId(Integer deleteCommentId) {
this.deleteCommentId = deleteCommentId;
}
private Comments selectGameComments;
public Comments getSelectGameComments() {
return selectGameComments;
}
public void setSelectGameComments(Comments selectGameComments) {
this.selectGameComments = selectGameComments;
}
@SuppressWarnings("unchecked")
@PostConstruct
public void init() {
gameApplicationEntity = new GameApplication();
gameCommentsEntity = new Comments();
this.gameCommentsEntity.setCommentText("");
}
public void saveNewComment(AjaxBehaviorEvent event){
if(this.gameCommentsEntity.getCommentText() != null){
if(this.gameCommentsEntity.getCommentText().length() > 0){
if(gameCommentsEntity.getCommentId() == null){
gameCommentsEntity.setGameApplication(this.gamerServiceUtil.getGameApplicationService().getGameApplicationByGameApplicationId(gameCommentsEntity.getGameApplication().getGameApplication()));
gameCommentsEntity.setCommentDt(maxDate);
gameCommentsEntity.setCommentBy(getUserId());
}
this.gamerServiceUtil.getGameCommentsService().save(gameCommentsEntity);
this.setGameCommentsList(this.gamerServiceUtil.getGameCommentsService().getCommentsByGameApplicationId(gameCommentsEntity.getGameApplication().getGameApplicationId()));
PrimeFaces.current().ajax().update("assesmentGameApplication:assesmentCommentsTable");
PrimeFaces.current().ajax().update("assesmentGameApplication:assesmentGameMain:assesmentCommentsTable");
PrimeFaces.current().ajax().update("assesmentGameApplication:assesmentGameMain:assesmentComments");
PrimeFaces.current().ajax().update("assesmentGameApplication:assesmentCommentsTable");
this.clearNewComment();
}
else{
PrimeFaces.current().executeScript("PF('waitSpinner').hide();");
FacesContext.getCurrentInstance().addMessage("assesmentCommentsMessageId", new FacesMessage (FacesMessage.SEVERITY_ERROR,"Invalid Comment", "Comments must be longer than zero characters in length"));
}
}
else{
PrimeFaces.current().executeScript("PF('waitSpinner').hide();");
FacesContext.getCurrentInstance().addMessage("assesmentCommentsMessageId", new FacesMessage (FacesMessage.SEVERITY_ERROR,"Error Saving Comment", "Error saving comment"));
}
}
public void deleteSelectedComment(){
if(this.getDeleteCommentId() != null){
Comments comment = this.gameServiceUtil.getGameCommentsService().getCommentByCommentId(this.getDeleteCommentId());
this.gameServiceUtil.getGameCommentsService().deleteCommentByCommentId(comment);
this.setGameCommentsList(this.gameServiceUtil.getGameCommentsService().getCommentsByGameApplicationId(gameCommentsEntity.getGameApplicationId()));
PrimeFaces.current().ajax().update("assesmentGameApplication:assesmentGameMain:assesmentCommentsTable");
PrimeFaces.current().ajax().update("assesmentGameApplication:assesmentCommentsTable");
}
this.setDeleteCommentId(null);
}
public void deleteSelectedCommentConfirmation(AjaxBehaviorEvent event){
Integer rowId = (Integer)event.getComponent().getAttributes().get("rowId");
this.setDeleteCommentId(this.gameCommentsList.get(rowId).getCommentId());
PrimeFaces.current().executeScript("PF('deleteCommentConfirmation').show();");
}
public void editSelectedComment(AjaxBehaviorEvent event){
Integer rowId = (Integer)event.getComponent().getAttributes().get("rowId");
this.setGameCommentsEntity(this.gamerServiceUtil.getGameCommentsService().getCommentByCommentId(this.gameCommentsList.get(rowId).getCommentId()));
this.setNewCommentNotReady(false);
PrimeFaces.current().ajax().update("assesmentGameApplication:saveCommentButton");
PrimeFaces.current().ajax().update("assesmentGameApplication:clearCommentButton");
PrimeFaces.current().ajax().update("assesmentGameApplication:assesmentGameMain:assesmentComments");
PrimeFaces.current().ajax().update("assesmentGameApplication:assesmentComments");
}
}
Game Application Entity
@Entity
@Table(name = "Game_Application")
@NamedQuery(name = "GameApplication.findAll", query = "SELECT g FROM GameApplication g")
public class GameApplication implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "application_id")
private Long GameApplicationId;
@Column(name = "number")
private String number; //immutable
@Column(name = "capacity")
private Integer capacity;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "building_id")
private Building building; //immutable
GameApplication() {
// default constructor
}
public GameApplication(Building building, String number) {
// constructor with required field
notNull(building, "Method called with null parameter (application)");
notNull(number, "Method called with null parameter (name)");
this.building = building;
this.number = number;
}
@Override
public boolean equals(final Object otherObj) {
if ((otherObj == null) || !(otherObj instanceof GameApplication)) {
return false;
}
// a room can be uniquely identified by it's number and the building it belongs to; normally I would use a UUID in any case but this is just to illustrate the usage of getId()
final GameApplication other = (GameApplication) otherObj;
return new EqualsBuilder().append(getNumber(), other.getNumber())
.append(getBuilding().getId(), other.getBuilding().getId())
.isEquals();
//this assumes that Building.id is annotated with @Access(value = AccessType.PROPERTY)
}
public Building getBuilding() {
return building;
}
public Long getGameApplicationId() {
return gameApplicationId;
}
public void setGameApplicationId(Long gameApplicationId) {
this.gameApplicationId = gameApplicationId;
}
public String getNumber() {
return number;
}
public void setCapacity(Integer capacity) {
this.capacity = capacity;
}
//no setters for number, building nor id
}
///////////// This is the table where the comments gets stored
@Entity
@Table(name = "GAME_COMMENTS")
@NamedQuery(name = "Comments.findAll", query = "SELECT g FROM Comments g")
public class Comments implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name = "COMMENT_ID_GENERATOR", sequenceName = "COMMENT_ID_SEQ", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "COMMENT_ID_GENERATOR")
@Column(name = "GAME_COMMENT_ID")
private Integer commentId;
@ManyToOne(targetEntity = GameApplication.class, fetch = FetchType.LAZY)
@JoinColumn(name = "GAME_APPLICATION_ID", nullable = false)
private GameApplication gameApplication;
@Column(name = "COMMENT_TEXT")
private String commentText;
@Column(name = "COMMENT_BY")
private String commentBy;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "COMMENT_DT")
private Date commentDt;
public GameApplication getGameApplication() {
return gameApplication;
}
public void setGameApplication(GameApplication gameApplication) {
this.gameApplication = gameApplication;
}
public Comments() {
}
public Integer getCommentId() {
return commentId;
}
public void setCommentId(Integer commentId) {
this.commentId = commentId;
}
public String getCommentText() {
return commentText;
}
public void setCommentText(String commentText) {
this.commentText = commentText;
}
public String getCommentBy() {
return commentBy;
}
public void setCommentBy(String commentBy) {
this.commentBy = commentBy;
}
public Date getCommentDt() {
return commentDt;
}
public void setCommentDt(Date commentDt) {
this.commentDt = commentDt;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (commentId ^ (commentId >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Comments other = (Comments) obj;
if (commentId != other.commentId)
return false;
return true;
}
@Override
public String toString() {
return "game=" + commentId
+ " ]";
}
}
///////////////////////
public interface GameCommentsRepository extends JpaRepository<Comments, Long>,
QueryDslPredicateExecutor<Comments> {
@Query("select obj from Comments obj where obj.gameApplication.gameApplicationId=:gameApplicationId order by obj.commentDt")
public List<Comments> getCommentsByGameApplicationId(
@Param("gameApplicationId") Long gameApplicationId);
@Query("select obj from Comments obj where obj.commentId=:commentId")
public Comments getCommentsByCommentId(@Param("commentId") long commentId);
}
///////////
///// ServiceUtilityclass
@ManagedProperty(value = "#{gameCommentsService}")
private transient GameCommentsService gameCommentsService;
public GameCommentsService getGameCommentsService() {
if (getGameCommentsService == null) {
getGameCommentsService = FacesContextUtils.getWebApplicationContext(
FacesContext.getCurrentInstance()).getBean(
GameCommentsService.class);
}
return getGameCommentsService;
}
public void setGameCommentsService(GameCommentsService gameCommentsService) {
this.gameCommentsService = gameCommentsService;
}
///// Interface
public interface GameCommentsService {
public Comments save(Comments gameApplication);
public Comments update(Comments gameApplication);
public List<Comments> getCommentsByGameApplicationId(Long gameApplicationId);
public Comments getCommentByCommentId(long commentId);
public void deleteCommentByCommentId(Comments comment);
}
///// Service Class
@Service("gameCommentsService")
public class gameCommentsServiceImpl implements GameCommentsService, Serializable {
private static final Logger logger = LoggerFactory
.getLogger(gameCommentsServiceImpl.class);
private static final long serialVersionUID = 1L;
@Resource
private transient JdbcTemplate jdbcTemplate;
@Resource
private GameCommentsRepository gameCommentsRepository;
public void setGameCommentsRepository(
GameCommentsRepository gameCommentsRepository) {
this.gameCommentsRepository = gameCommentsRepository;
}
@Override
@Transactional
public Comments save(Comments comments) {
try {
comments = gameCommentsRepository.save(comments);
return comments;
} catch (RuntimeException re) {
throw re;
}
}
@Override
@Transactional
public Comments update(Comments comments) {
try {
comments = gameCommentsRepository.save(comments);
return comments;
} catch (RuntimeException re) {
throw re;
}
}
@Override
public List<Comments> getCommentsByGameApplicationId(Long gameApplicationId) {
try {
List<Comments> comments = gameCommentsRepository
.getCommentsByGameApplicationId(gameApplicationId);
return comments;
} catch (RuntimeException re) {
throw re;
}
}
@Override
@Transactional
public void deleteCommentByCommentId(Comments comment) {
logger.debug("deleteCommentByCommentId");
this.gameCommentsRepository.delete(comment);
}
@Override
public Comments getCommentByCommentId(long commentId) {
logger.debug("getCommentByCommentId: " + commentId);
try {
Comments comment = this.gameCommentsRepository
.getCommentsByCommentId(commentId);
return comment;
} catch (RuntimeException re) {
logger.error("getCommentByCommentId failed", re);
throw re;
}
}
}
Представление страницы
[ Input Text Area ]
;Save Button;
Data Table ---------- Actions
Comment one ;Delete: ;Edit;
Comment two ;Delete: ;Edit;
Comment three ;Delete: ;Edit;