Hi guys, for any of you who have used the ajaxformloop over the years and have struggled not to have to use @Persist and handle the save on form submission know that it has been a challenge. I managed to come up with the following solution this morning that thus far seems to work very well. I'd like to share it so that it can be picked apart, but also provide another working example demonstrating how this can be done.
TimeSheet is a parent entity containing a one to may relationship with EffortAllocation. <div t:type="AjaxFormLoop" t:source="timeSheet.effortAllocations" t:value="effortAllocation" t:encoder="encoder"> <t:textfield t:id="activityCode" value="effortAllocation.activityCode" t:validate="required/> <t:removerowlink>remove</t:removerowlink> </div> public ValueEncoder<EffortAllocation> getEncoder() { return new ValueEncoder<TimeSheet>() { @Override public String toClient(EffortAllocationv) { //getTempId is a a transient temp id in the effortallocation entity //example Long tempId = 0 - System.nanoTime(); //This is used to create a unique client id. String id = v.getId() != null ? v.getId().toString() : v.getTempId().toString(); return id; } @Override public EffortAllocationtoValue(String toValue) { Long id = Long.parseLong(toValue); if (id > 0) { //timeSheet object is populated in onActivate / setupRender from the database for (EffortAllocation effortAllocation : timeSheet.getEffortAllocations()) { if (effortAllocation.getId().equals(id)) { return effortAllocation; } } } return new EffortAllocation(timeSheet); } }; } void onPrepareForSubmit() { this.isSubmitAction = true; } public EffortAllocation getEffortAllocation() { return effortAllocation; } public void setEffortAllocation(EffortAllocation effortAllocation) { this.effortAllocation = effortAllocation; if (isSubmitAction) { //transient field within the effort allocation entity //this is used to determine whether or not the object should be removed //See removeEffortAllocations code effortAllocation.setHoldObj(true); if (effortAllocation.getId() == null && form.isValid()) { timeSheet.getEffortAllocations().add(effortAllocation); } } } //Call this method after form example, example onValidate. This will remove deleted rows where //isHoldObj hasn't been set to true in the set method. public void removeEffortAllocations() { List<EffortAllocation> effortAllocations = new ArrayList<>(); for (EffortAllocation _effortAllocation : timeSheet.getEffortAllocations()) { if (!_effortAllocation.isHoldObj()) { effortAllocations.add(_effortAllocation); } } if (!effortAllocations.isEmpty()) { timeSheet.getEffortAllocations().removeAll(effortAllocations); } } void onRemoveRow(EffortAllocation effortAllocation) { } -- George Christman www.CarDaddy.com P.O. Box 735 Johnstown, New York