Jsf 模型已更新,但更改丢失

Jsf 模型已更新,但更改丢失,jsf,jsf-2.2,Jsf,Jsf 2.2,在下面的表格中,一个人可以与汽车一起进入。例如,用户可以通过单击数据表行上的“减号”命令按钮来移除车辆。但是, 当“减号”命令按钮为immediate=false时,车辆的移除不起作用,因为验证开始(需要人员的姓氏),验证按预期进行 如果它是immediate=true,则保存无法正常工作。示例:列表中有三辆车,“福特”(排名第二)被删除。删除操作似乎很好,浏览器正确地反映了更改。然而,当通过savePerson方法触发保存时,它显示列表中的最后一辆车(丰田)已被删除,而不是福特。在保存人员时

在下面的表格中,一个人可以与汽车一起进入。例如,用户可以通过单击数据表行上的“减号”命令按钮来移除车辆。但是,

  • 当“减号”命令按钮为immediate=false时,车辆的移除不起作用,因为验证开始(需要人员的姓氏),验证按预期进行
  • 如果它是immediate=true,则保存无法正常工作。示例:列表中有三辆车,“福特”(排名第二)被删除。删除操作似乎很好,浏览器正确地反映了更改。然而,当通过savePerson方法触发保存时,它显示列表中的最后一辆车(丰田)已被删除,而不是福特。在保存人员时,我可以做些什么来反映更改
下面是bean的日志输出:

removing car Car{brand='Ford'}
remaining car Car{brand='Porsche'}
remaining car Car{brand='Toyota'}
saving person
saving car Car{brand='Porsche'}
saving car Car{brand='Ford'}
JSF


人
烙印
选择权
豆子

import com.google.common.collect.list;
导入de.dgr.question.Car;
导入de.dgr.question.Person;
导入org.slf4j.Logger;
导入javax.annotation.PostConstruct;
导入javax.faces.bean.ManagedBean;
导入javax.faces.bean.ViewScoped;
导入javax.inject.inject;
导入java.io.Serializable;
导入java.util.List;
@ManagedBean(name=“table”)
@视域
公共类TableController实现了可序列化{
@注入
私人日志记录器;
私人;
@施工后
公共void init(){
列出汽车=列出。newArrayList(新车(“保时捷”)、新车(“福特”)、新车(“丰田”);
person=新的person();
人.车(车);
}
公共字符串savePerson(){
日志信息(“->保存人”);
for(Car-Car:person.getCars()){
log.info(“保存汽车{}”,汽车);
}
返回null;
}
公共字符串removeCar(最终Car carToDelete){
log.info(“删除车辆{}”,carToDelete);
person.getCars().remove(carToDelete);
for(Car-Car:person.getCars()){
log.info(“剩余车辆{}”,车辆);
}
返回null;
}
公共字符串addCar(){
日志信息(“添加空车”);
person.getCars().add(新车());
返回null;
}
公众人物{
返回人;
}
公众人士(最终人士){
这个人=人;
}
}

感谢BalusC为我提供的链接,我实现了以下解决方案

immediate=true在任何情况下都是错误的,因为当输入新车并删除其中一辆时,需要使用表单数据更新模型(组件)。否则,在添加/删除汽车时,表单中已填写的数据将丢失(加号/减号命令按钮)

这意味着需要处理表单的所有输入组件,包括所需的组件“last”,以便使用该数据更新模型。为避免在添加/删除车辆时验证所需的“最后一个”组件,并仅在按下保存按钮时进行验证,使用了[的解决方案]

然而,最后一点似乎只有在未指定ajax=“false”时才起作用。如果是这样,则param[save.clientId]似乎总是空的。只有在ajax=“true”(这是默认值)时,参数才会有值

更改jsf页面:

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

    <ui:define name="content">
        <h:form id="formChanges" prependId="false">
            <p:accordionPanel id="accPanel" prependId="false">

                <p:tab title="Cars">
                    <h:panelGroup id="panelNewData">
                        <p:panelGrid columns="2">
                            <f:facet name="header">Person</f:facet>
                            <p:outputLabel value="Last" for="last"/>
                            <p:inputText id="last" value="#{table.person.last}"
                                         required="#{not empty param[save.clientId]}" />

                            <p:outputLabel value="First" for="first"/>
                            <p:inputText id="first" value="#{table.person.first}"/>
                        </p:panelGrid>

                        <p:dataTable var="car" value="#{table.person.cars}">
                            <p:column>
                                <f:facet name="header">Brand</f:facet>
                                <p:inputText value="#{car.brand}"/>
                            </p:column>
                            <p:column>
                                <f:facet name="header">Options</f:facet>
                                <p:commandButton value="#{msgs.minus}"
                                                 action="#{table.removeCar(car)}"
                                                 process="panelNewData"
                                                 update="panelNewData"/>
                            </p:column>
                        </p:dataTable>
                        <p:commandButton value="#{msgs.plus}" action="#{table.addCar}"
                                         process="panelNewData" update="accPanel"/>

                        <p:spacer height="10"/>
                        <p:commandButton id="save" binding="#{save}" value="#{msgs.save}"
                                         icon="ui-icon-check" action="#{table.savePerson}" 
                                         update="accPanel"/>
                    </h:panelGroup>
                </p:tab>
            </p:accordionPanel>
        </h:form>
    </ui:define>

</ui:composition>

人
烙印
选择权

这个问题有点含糊不清,您可以接受哪一个作为dupe?或者,如果您认为问题/答案没有为您在评论中发布的链接提供新信息,请随时删除该帖子,并感谢您的帮助!!!
import com.google.common.collect.Lists;
import de.dgr.question.Car;
import de.dgr.question.Person;
import org.slf4j.Logger;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import java.io.Serializable;
import java.util.List;

@ManagedBean(name = "table")
@ViewScoped
public class TableController implements Serializable {

    @Inject
    private Logger log;

    private Person person;

    @PostConstruct
    public void init() {
        List<Car> cars = Lists.newArrayList(new Car("Porsche"), new Car("Ford"), new Car("Toyota"));
        person = new Person();
        person.setCars(cars);
    }

    public String savePerson() {
        log.info("-> saving person");
        for (Car car :  person.getCars()) {
            log.info("saving car {}", car);
        }

        return null;
    }

    public String removeCar(final Car carToDelete) {
        log.info("removing car {}", carToDelete);
        person.getCars().remove(carToDelete);
        for (Car car :  person.getCars()) {
            log.info("remaining car {}", car);
        }

        return null;
    }

    public String addCar() {
        log.info("adding empty car");
        person.getCars().add(new Car());

        return null;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(final Person person) {
        this.person = person;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition template="/META-INF/templates/template.xhtml"
                xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:p="http://primefaces.org/ui">

    <ui:define name="content">
        <h:form id="formChanges" prependId="false">
            <p:accordionPanel id="accPanel" prependId="false">

                <p:tab title="Cars">
                    <h:panelGroup id="panelNewData">
                        <p:panelGrid columns="2">
                            <f:facet name="header">Person</f:facet>
                            <p:outputLabel value="Last" for="last"/>
                            <p:inputText id="last" value="#{table.person.last}"
                                         required="#{not empty param[save.clientId]}" />

                            <p:outputLabel value="First" for="first"/>
                            <p:inputText id="first" value="#{table.person.first}"/>
                        </p:panelGrid>

                        <p:dataTable var="car" value="#{table.person.cars}">
                            <p:column>
                                <f:facet name="header">Brand</f:facet>
                                <p:inputText value="#{car.brand}"/>
                            </p:column>
                            <p:column>
                                <f:facet name="header">Options</f:facet>
                                <p:commandButton value="#{msgs.minus}"
                                                 action="#{table.removeCar(car)}"
                                                 process="panelNewData"
                                                 update="panelNewData"/>
                            </p:column>
                        </p:dataTable>
                        <p:commandButton value="#{msgs.plus}" action="#{table.addCar}"
                                         process="panelNewData" update="accPanel"/>

                        <p:spacer height="10"/>
                        <p:commandButton id="save" binding="#{save}" value="#{msgs.save}"
                                         icon="ui-icon-check" action="#{table.savePerson}" 
                                         update="accPanel"/>
                    </h:panelGroup>
                </p:tab>
            </p:accordionPanel>
        </h:form>
    </ui:define>

</ui:composition>