tags:

views:

35

answers:

1

The bug is the inputTextarea I have below. Only the last row can record any input from the inputTextarea, in other word, only the last row, hook it value to #{PostComment.comment.comment}. Why is this?

<h:form id="userCommentList" >
   <p:dataTable value="#{CentralFeed.profileComments}" var="item">
        <p:column>        
           <!-- Original Comment -->         
           <h:outputText value="#{item.comment}"/> &nbsp;              

           <!-- ****BUG IS THIS INPUTTEXTAREA BELOW*** -->
           <h:inputTextarea id="keyword" value="#{PostComment.comment.comment}"/> &nbsp;

           <p:commandButton actionListener="#{PostComment.postProfileComment(item.id)}"
                                             value="Post" update="userCommentList" />
        </p:column>                                                                                   
   </p:dataTable>
</h:form>

EDIT I change the inputTextarea and commandButton like you suggest BalusC. And inside Comment entity I add in another field call newComment, so Comment look like this

Comment
+ id
+ comment
+ newComment --> I have @Transient to this field so it wont map to the database. I also set its default value to the empty string in the constructor
+ ...

...
<p:column>
    ...
    <h:inputTextarea id="keyword" value="#{item.newComment}" rows="2" />
    <p:commandButton actionListener="#{PostComment.postReply(item)}" value="Post" />
</p:column>

I hope the item.newComment would hold the value I just type in, so when I pass the object item to postReply, I can extract the content of newComment out, however it is an empty string. So whatever I type in does not bind to newComment. Any idea why?

+2  A: 

You're in essence binding the value of multiple textareas in a table to one and same bean property. During request processing JSF will update this property with the value of all textareas in the table, each overriding the previous one everytime until with the one in the last row. That's why you will see only the value of one in the last row.

You need to bind the textarea value to the row object, which is #{item} in your case. E.g.

<h:inputTextarea id="keyword" value="#{item.newComment}"/>
BalusC
is the `newComment` mean anything special or is it just a field inside my object, BalusC?
Harry Pham
It's just an example. You can even use `#{item.comment.message}`. As long as it ends up in a `String` property.
BalusC
I think you might have misunderstand me a bit. What I want is: whatever I type into this inputTextarea, that information will create a new entry in my dataBase. It seems to me what you suggest, would override the value at the rows (since you bind to an exist object, not a new object). So inside my `PostComment` bean, I have `Comment comment = new Comment()`, so I want to bind whatever I just type to `comment`, so then once I persist, it become a new entry in `Comment` table.
Harry Pham
Just do this job in `postProfileComment()` method. Check if the new comment has been entered, then persist it.
BalusC
Hi BalusC, been busy so I havent got a chance to test it out. Well, I finally tried out your idea, but I still ran into some problem. I updated my original post, will you please take a look at them?
Harry Pham
Interesting. Is it also empty when you traverse it from the list/datamodel directly instead of the passed-in argument? I'd however expect both to point to the same reference... What's the bean scope? Request or View?
BalusC
Request scoped, BalusC. And I believe they both point to the same reference, but let me make.
Harry Pham
I tested it with DataModel. `newComment` still is empty if I use `getRowData`.
Harry Pham
Odd. Try `<h:commandButton>` or `<p:commandButton ajax="false">` to exclude one and other.
BalusC
I tried that, does not fix it. Could this be because the `List` is not in managed state?
Harry Pham
Is the submitted value present as request parameter? (check by Firebug, Fiddler or `getRequestParameterMap()`). I should maybe also note that I am still assuming that you didn't change other parts of the code since the original problem of only the last value being submitted, e.g. adding a nested form, a rendered/disabled attribute, etc.
BalusC
I have not changed the code: There are no nested form, the `h:commandButton` only have `action` and `value` attribute. Now if I put this `Map<String, String> map = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();` inside the `postReply()` method, I see interesting things. One of the element in the `map` actually contain the content of what I typed: `"userCommentList:j_idt38:0:keyword => common, what do I see"` `userCommentList` is the id of the form, `keyword` is the id of the inputTextarea, and `common, ...` is what I type in.
Harry Pham
OK, it's been submitted, but the model is not been updated. Isn't there an `immediate="true"` on either input or button? Remove it. If that was not the cause, I'd start debugging to see if the getter of the datamodel returned the right datamodel and the setter of the `newComment` was invoked anyway and that during the right phases. I suspect a mistake in datamodel loading/preserving and that the model cannot be found or that it was been overridden with a new reload.
BalusC
well there is no `immediate=true`, and but setter method of newComment got invoke twice. One is to set the value that I just type to the `newComment`, the second time, set empty string to the newComment
Harry Pham
That second set is suspicious. Don't you have another input field which sets the same property somewhere further in the table?
BalusC
ohhh yeah, I have another one down, that explain the second setter, damn, I am stupid
Harry Pham
Well you've at least learnt some debugging techniques ;)
BalusC
I am sorry but how can I check what phase does DataModel get call, like what you mention earlier?
Harry Pham
Log `FacesContext#getCurrentPhaseId()` in the getter or determine it in the variables section of the debugger.
BalusC
it is at phase 5, `INVOKE_APPLICATION`
Harry Pham
Well, I'd expect to see it only inside the action method, not in the getter (or you must be calling the getter from inside the action method instead of just accessing the local variable?)
BalusC
That is correct, I call the getter of my DataModel from the action method. My DataModel is in my SessionScoped bean, and my action method is in RequestScoped bean.
Harry Pham
OK, is your comment thing now working? Cheers, I'm going offline in order to buy myself a new laptop :)
BalusC
Well hope you get a good deal on your laptop. Well it still not working. But now I know why the `newComment` got reset. If you take a look at my code above, dataTable invoke getProfileComments(). And in there, via my EJB, I query the entity, then I set up my DataModel here. this method get call a lot when I submit the comment. I debug, this method get call more than 10 times, going through 1-4 phase, each phase call multiples time. Is it normal? But what reset `newComment` is right after the `setNewComment()`, getProfileComments() got call, which then query the entity, hence reset what I type
Harry Pham
From my comment above, I have a question. Is it normal to have getProfileComments() call over 12 times going through phase 1-4, each phase call this method 3-4 times. Right after this, `setNewComment()` get called, then immediate `getProfileComments()` get called again with phase id 5. Then `postReply()` inside RequestScoped bean `PostComment` get call, then `getProfileComments()` get call again with phase id 6 (3-4 times). This is definitely not normal. Definitely something wrong here. Any idea why, balusC?
Harry Pham
Since this is a new problem, I guess I make a new post http://stackoverflow.com/questions/3973198/hdatatable-valuemybean-xxx-getxxx-get-called-so-many-times-why . I rewrite the code in the simplest form to make sure I did not make any mistake. If you have sometimes, please take a look at them. Thank you for your help
Harry Pham
I've answered your other question. That it's called many times is normal, it's just to **access** the model data. Data loading should however definitely not go in the getter. As to the deal, well, I'm hesitating between a Dell Inspirion 17 and HP Pavilion DV7 :) I'll read some reviews and decide tomorrow.
BalusC
Thank you BalusC. Base on your answer, I guess if I move the query database off the getter, then it should fix my bug. Let me try that. About the laptop, have you ever think of going for a MAC. I doubt it the first time but man, I love it now :D
Harry Pham
Move the business logic off the getter fix my issue. Thank you. Ohh one more thing, when i see you wrap DataModel around the List, and later edit the list like add or delete entry, I dont see u re-update the DataModel. Does DataModel smart enough to know that the List is changes.
Harry Pham
Indeed, it just holds the reference to the list, not the list itself. Nice thing, OO, huh? :)
BalusC
yup very nice. Thank you
Harry Pham