Ao adicionar ou excluir linhas automaticamente de uma tabela de dados JSF, você deve renderizar novamente a tabela inteira em vez de apenas renderizar novamente uma linha específica.
A desvantagem disso é que, se você tiver uma tabela de dados rolável, perderá sua posição de rolagem.
Por exemplo
Digamos que você tenha uma tabela de dados que mostra 20 linhas e qualquer coisa acima de 20 linhas, você terá que rolar para baixo para ver essas linhas. Digamos que tenhamos um botão de exclusão para cada linha e se você rolar para baixo e excluir a linha 49, por exemplo (provavelmente, é claro), terá que renderizar novamente a tabela de dados e a posição de rolagem estará no topo novamente.
Recentemente, tive que encontrar uma solução para esse problema e, na verdade, acabou sendo muito mais fácil do que eu esperava.
O truque
A chave é armazenar a posição de rolagem em uma variável javascript e, em seguida, quando a ação do botão adicionar ou excluir for concluída, definir a posição de rolagem via javascript.
Código
Você pode ver que estou usando um a4j: commandButton (só porque sou forçado a fazer atualizações em um aplicativo richfaces no JSF 1.2, caso contrário, eu usaria um h: commandButton com a tag f: ajax ou melhor ainda, uma tabela de dados primefaces com ap: commandButton)
Tabela de dados JSF
<h:dataTable value="#{blah.blah}" var="#{blah}" id="table">
<h:column>
<a4j:commandButton value="del"
onclick="confirm('Are you sure you want to delete this attribute?')"
onmousedown="saveScrollPosition();"
oncomplete="setScrollPosition();"
reRender="table"
actionListener="#{backing.deleteRow}" immediate="true"/>
</h:column>
</h:dataTable>
Javascript
var scrollPosition;
function saveScrollPosition() {
scrollPosition = $('#table').scrollTop();
}
function setScrollPosition() {
$('#table').scrollTop(scrollPosition);
}
É isso aí. Um pouco de js, um pouco de magia e um cliente um pouco mais feliz. Felicidades.