2

i have a repeating form like this:

<ui:repeat var="blogPost" value="#{blogPosts}">
    <h:form>
        <div class="full">
            <label for="newcomment">write a comment<br/></label> 
            <h:inputTextarea value="#{commentController.commentText}" id="commentText" rows="10" cols="40" />
        </div>
        <div class="full">
            <h:commandButton action="#{commentController.setComment()}" value="write comment">      
                <f:setPropertyActionListener target="#{commentController.blogPostId}" value="#{blogPost.id}" />
            </h:commandButton>  
    </h:form>
</ui:repeat>

I found this Post form BalusC - helped me a lot so i have now the blogPostID in my controller!

But the problem is:
The form is repeating 1 - x times!

So, if i have 3 forms rendered, all textareas use the same commentController.commentText

So if i write something in the first textarea, the 2nd and 3rd are deleting the commentText in the Controller.
If i put something into the 3rd textarea, it works!

Any idea how to fix tis problem?
thanks in advance!

p.s. i also tried to have the <h:form> outside the <ui:repeat> - makes no difference

Here are the classes:

The Controller:

@ManagedBean(name="commentController")
@RequestScoped
public class CommentController {

@EJB
private CommentProvider commentProvider;

private String commentText;

private List<String> commentTextListToWrite;

private Comment comment;

private Integer blogPostId;




@PostConstruct
protected void init(){
    comment = new Comment();
    commentTextListToWrite = new ArrayList<String>();
}

public void setComment(){
    int count = 0;
    for (String ct : commentTextListToWrite) {
        System.out.println("test " + count + ct);
        count++;
    }

}

/**
 * Returns the commentText.
 *
 * @return the commentText.
 */
public String getCommentText() {
    return commentText;
}

/**
 * Sets the commentText.
 *
 * @param commentText the commentText to set.
 */
public void setCommentText(String commentText) {
    this.commentText = commentText;
}

public void delete(Comment comment){
    commentProvider.delete(comment);
}

/**
 * Returns the blogPostId.
 *
 * @return the blogPostId.
 */
public Integer getBlogPostId() {
    return blogPostId;
}

/**
 * Sets the blogPostId.
 *
 * @param blogPostId the blogPostId to set.
 */
public void setBlogPostId(Integer blogPostId) {
    this.blogPostId = blogPostId;
}

/**
 * Returns the commentTextListToWrite.
 *
 * @return the commentTextListToWrite.
 */
public List<String> getCommentTextListToWrite() {
    return commentTextListToWrite;
}

/**
 * Sets the commentTextListToWrite.
 *
 * @param commentTextListToWrite the commentTextListToWrite to set.
 */
public void setCommentTextListToWrite(List<String> commentTextListToWrite) {
    this.commentTextListToWrite = commentTextListToWrite;
}

}

index.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:s="http://jboss.com/products/seam/taglib"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    template="/WEB-INF/templates/default.xhtml">

    <ui:define name="content">


            <h2>Show all BlogPosts</h2>

            <ui:repeat var="blogPost" value="#{blogPosts}" varStatus="loop" >
        <h:form>    
                <div class="posting">
                    <h3>#{blogPost.headline}</h3>
                    <div class="posts">#{blogPost.blogPost}</div>
                    <div class="posts">
                            vom #{blogPost.date} mit ID: #{blogPost.id}<br />
                        <h:commandButton value="delete" action="#{blogPostController.delete(blogPost)}" />
                        </div>
                    </div>


                <ui:include src="pages/components/_write-comment.xhtml">
                    <ui:param name="blogPostId" value="#{blogPost.id}" />
                    <ui:param name="loopCount" value="#{loop.index}" />
                </ui:include>  


                </h:form>
            </ui:repeat>
        </ui:define>
</ui:composition>

_write-comment.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">


            <div class="full">
                <span class="half"> 
                    <label for="newcomment">write comment</label><br/> 
                    <h:outputLabel for="commentText" value="loop index #{loopCount}" />
                        <h:inputTextarea value="#{commentController.commentText[loopCount]}" id="commentText" rows="10" cols="40">
                    </h:inputTextarea>
                </span> 
                <span class="quarter error"> 
                    <h:message id="newcomment_error" for="newcomment" value="fehler" />
                </span>
            </div>
            <div class="full">
                <h:commandButton action="#{commentController.setComment()}" value="write comment">

                </h:commandButton>
            </div>

</ui:composition>

is the Setter of the List correct?

there is (at the moment) no real error, but the system out fails, because the list is empty (the System.Out just stands for another function... it's just for testing!)

Community
  • 1
  • 1
Joergi
  • 1,527
  • 3
  • 39
  • 82

1 Answers1

3

Can you please post the Managed Bean code as well. From what I can see the commentText attribute in your commentController is a simple String instead of a List<String>. When you have for example three text areas you must have three different variables which should store the textarea content. This is why you need a list there.

Here you can read some more details because I had the same problem as you.

Knowing all that your code should look like this:

Managed Bean:

private List<String> commentText;
// get& set

Facelet:

<ui:repeat var="blogPost" value="#{blogPosts}" varStatus = "loop">
<h:form>
    <div class="full">
        <label for="newComment" value = "Write a comment" />
        <h:inputTextarea id = "newComment" value="#{commentController.commentText[loop.index]}" rows="10" cols="40" />
    </div>
    <div class="full">
        <h:commandButton action="#{commentController.setComment()}" value="write comment" />
    </div>        
</h:form>

Some other pointers:

  • avoid that <br /> in the label tag.
  • pay attention to the textarea id attribute. It should be the same as that linked by the label. If not, you will receive some view warnings because the framework will not be able to find the IDs you specified. Don't worry about the IDs being identical in the ui:repeat loop. If you analyse the HTML code you'll see that SF handle the IDs and they differ.

LE:

I think that the reason you are having this problem is that you allocated memory for the List<String> but the list does not contain any String. The framework wants to place values into the List but there is no String object to be setted.

To solve this, in the CommentController you have to add the needed empty Strings into the List:

@PostConstruct
protected void init(){
    comment = new Comment();
    commentTextListToWrite = new ArrayList<String>();

    for (int i = 0; i < blogPosts.size(); i++){
            commentTextListToWrite.add(new String());
    }
}

blogPosts.size() is the blogPosts attribute you are using on the <ui:repeat> tag. I can imagine that you are able to access it in the CommentController as well. This way, every time you instantiate a CommentController entity, the commentTextListToWrite will be instantiated and will contain the required number of empty Strings which will be completed on the view.

Community
  • 1
  • 1
Ionut
  • 2,788
  • 6
  • 29
  • 46
  • hi lonut, thx for your reply. you are right, it was really only a `String` and not a `List` but if i try to set it, as you mentioned, it's not working... i have this 3 files: index.html (in line 32 i include the _write-comment.xhtml) http://pastebin.com/6k8ZDR5A _write-comment.xhtml http://pastebin.com/KXGAeuSi CommentController.java http://pastebin.com/AUrCc0MS hope this helps? i see what you mean, but it's not working at the moment... i make a for each through the List commentTextListToWrite but it's empty :( – Joergi Feb 27 '12 at 17:09
  • @Joerg Can you please provide more details regarding the error you are getting? At a firs glance the code looks ok. Can you update the question and post the rendered HTML code? – Ionut Feb 27 '12 at 17:43
  • @lonut: ok, i edited the original... maybe my setter for the list is wrong in this case? – Joergi Feb 27 '12 at 18:34
  • 1
    @Joerg I updated my answer. Check the LE part. You didn't place the empty String into the `List` therefore there was nothing to be setted. It should work now. – Ionut Feb 27 '12 at 19:00
  • 1
    @Lonut: thanks a lot for helping! i found now the error: i have to change the order of the `ui:repeat` and the `h:form` - now it's working! – Joergi Feb 27 '12 at 20:39