# Zugriff Validator in Tabelle (ui:repeat) auf andere Felder



## Raphalon (7. Feb 2012)

Hallo,

in einer Tabelle (z.B. ui:repeat) möchte ich drei Felder nebeneinander stellen:

eine selectBooleanCheckbox, welche anzeigt, ob die folgenden beiden Felder editierbar sein sollen
eine inputText mit einem String einer Bean; wird angezeigt, wenn die checkbox den Haken hat (wird über das Attribut "rendered" bestimmt) oder outputText, wenn checkbox false (dann nicht editierbar)
nochmals wie 2.
2. und 3. sind Name und Vorname eines Users (weitere Felder folgen, ist aber hier nicht wichtig).

Der Anwender setzt nun z.B. an der Checkbox den Haken, es erfolg ein submit(), die Seite wird neu gerendered und damit inputText dargestellt. Der User ändert etwas und soll es dann speichern können.

Ich möchte nun an inputText einen Validator anbringen, welcher aber - wenn die Validierung fehlschlägt - auch die Checkbox wieder aktiviert. Kann ich das nämlich nicht und schlägt die Validierung fehl, dann hat die Checkbox keinen Haken mehr (weil direkt auf die Render-Phase gesprungen wird, ohne in der Bean den Wert entsprechend zu setzen). Ich müsste also im Validator direkt auf diesen einzelnen (von vielen anderen) User zugreifen und sein "editable" Flag wieder setzen können.

Ein Versuch war, den Validator in der Bean selbst zu verwenden, was aber natürlich keinen Sinn macht - ein Validator aktualisiert die Werte in der Bean ja nicht. Wohl kann man mit dem component Feld des Validators (
	
	
	
	





```
javax.faces.validator.Validator.validate(FacesContext context, UIComponent component, java.lang.Object value)
```
) auf die anderen Komponenten des Requests zugreifen, aber wie soll ich da die "richtige" Checkbox herausfinden?

Wie macht man das? Geht das überhaupt?

Gruß,

Raphalon


----------



## Sym (8. Feb 2012)

Ich gebe das noch mal wieder, wie ich das verstanden habe:

Checkbox wird gesetzt -> es wird das InputText-Feld aktiviert
User trägt im InputText etwas ein -> Wird dann ein Submit durchgeführt?
Checkbox wird automatisch deaktiviert (was so nicht sein soll)

Wie sieht Deine Bean aus? Welchen Scope hat diese?


----------



## Raphalon (9. Feb 2012)

Vorgang:

Die Checkbox wird gesetzt => es wird ein Submit ausgeführt, das inputText-Feld wird gerendered
User trägt im InputText etwas ("falsches") ein => ein Submit wird ausgeführt und die Validierung schlägt fehl, Haken der CheckBox ist immer noch gesetzt
Der Anwender könnte den Wert im InputText jetzt korrigieren und erneut einen submit ausführen, er entscheidet sich nun aber doch gegen das Editieren und nimmt den Haken aus der CheckBox (submit wird ausgeführt), so daß wieder der ursprüngliche Wert angezeigt werden soll.
Ergebnis: 1. der Haken ist weg, und 2. dennoch wird das InputText-Feld dargestellt. 

Ich würde aber erwarten, dass der Haken auch nach wie vor gesetzt ist, denn die Validierung schlug ja fehl, die Bean-Werte wurden nicht aktualisiert (kein "update model values") und damit auch nicht das editable flag des Datensatzes der Tabellenzeile.

Die Validierung war ursprünglich direkt am inputText-Feld (als 
	
	
	
	





```
<f:validateRegex pattern="(([a-zA-ZüÜöÖäÄß]){3,20})" />
```
) dann aber habe ich den Validator als Methode umgesetzt, weil ich dachte, ich könne irgendwie auf die Checkbox zugreifen.

Hier der Code des xhtml

```
<h:form>
	<table id="myTableFirst" class="tablesorter" cellspacing="1">
		<tbody>
			<ui:repeat value="#{userEditAll.entryList}" var="entry"
				varStatus="status">
				<h:panelGroup rendered="#{status.even}">
					<tr>
						<td class="evencenter"><h:selectBooleanCheckbox id="checkereven"
								value="#{entry.editable}" onclick="submit()" /></td>
						<td class="evenleft"><h:outputText
								value="#{entry.user.lastname}"
								rendered="#{not entry.editable}" /> <h:inputText
								id="nameeven" value="#{entry.user.lastname}"
								rendered="#{entry.editable}"
								validator="#{userEditAll.checkTextField}"
								validatorMessage="#{msgs.onlyLetters}">
							</h:inputText><br /> <h:message for="nameeven" errorClass="error" /></td>
						<td class="evenleft"><h:outputText
								value="#{entry.user.firstname}"
								rendered="#{not entry.editable}" /> <h:inputText
								id="firstnameeven" value="#{entry.user.firstname}"
								rendered="#{entry.editable}"
								validator="#{userEditAll.checkTextField}"
								validatorMessage="#{msgs.onlyLetters}">
							</h:inputText><br /> <h:message for="firstnameeven" errorClass="error" /></td>
					</tr>
				</h:panelGroup>
				<h:panelGroup rendered="#{status.odd}">
					<tr>
						<td class="oddcenter"><h:selectBooleanCheckbox id="checkerodd"
								value="#{entry.editable}" onclick="submit()" /></td>
						<td class="oddleft"><h:outputText
								value="#{entry.user.lastname}"
								rendered="#{not entry.editable}" /> <h:inputText
								id="nameodd" value="#{entry.user.lastname}"
								rendered="#{entry.editable}"
								validator="#{userEditAll.checkTextField}"
								validatorMessage="#{msgs.onlyLetters}">
							</h:inputText><br /> <h:message for="nameodd" errorClass="error" /></td>
						<td class="oddleft"><h:outputText
								value="#{entry.user.firstname}"
								rendered="#{not entry.editable}" /> <h:inputText
								id="firstnameodd" value="#{entry.user.firstname}"
								rendered="#{entry.editable}"
								validator="#{userEditAll.checkTextField}"
								validatorMessage="#{msgs.onlyLetters}">
							</h:inputText><br /> <h:message for="firstnameodd" errorClass="error" /></td>
					</tr>
				</h:panelGroup>
			</ui:repeat>
		</tbody>
	</table>
	<p>
		<h:commandButton value="#{msgs.send}" action="#{userEditAll.send}" />
		<h:commandButton value="#{msgs.cancel}"
			action="#{userEditAll.cancel}" immediate="true" />
	</p>
</h:form>
```

Verkürzter Code der Bean => diese ist in einer manual Conversation, welche erst invalidiert wird, wenn der User cancel klickt oder erfolgreich speichert.


```
@Named("userEditAll")
@Scope("manual")
@ViewController(viewIds = { ViewIds.ADMIN_EDITALL,
		ViewIds.ADMIN_EDITALL_CONFIRM, ViewIds.ADMIN_EDITALL_EMPTY })
@ConversationRequire(conversationNames = "userEditAll", entryPointViewIds = ViewIds.ADMIN_EDITALL, navigationAction = ViewIds.ADMIN_EDITALL)
public class UserEditAllBean implements Serializable {

	@Inject
	private UserService userService;
	private List<Rowcontent> entryList;

	@PostConstruct
	public void setEntryList() {
         // Hier werden die Daten aus der DB geholt und "entryList" gefüllt.
	}

	public List<Rowcontent> getEntryList() {
		return entryList;
	}

    [...]


	public class Rowcontent implements Serializable {

		private static final long serialVersionUID = 1L;
		private boolean editable;
		private boolean delete;
		private boolean changed;
		private boolean userLoggedIn;
		private User user;

		public Rowcontent() {
		}

		public Rowcontent(User user) {
			this.user = user;
		}

		public Rowcontent(User user, boolean userLoggedIn) {
			this.user = user;
			this.userLoggedIn = userLoggedIn;
		}

		public boolean getEditable() {
			return editable;
		}

		public void setEditable(boolean editable) {
			this.editable = editable;
		}

		public void setUserLoggedIn(boolean userLoggedIn) {
			this.userLoggedIn = userLoggedIn;
		}

		public boolean getUserLoggedIn() {
			return userLoggedIn;
		}

		public boolean getDelete() {
			return delete;
		}

		public void setDelete(boolean delete) {
			this.delete = delete;
		}

		public boolean getChanged() {
			return changed;
		}

		public void setChanged(boolean changed) {
			this.changed = changed;
		}

		public User getUser() {
			return user;
		}

		public void setUser(User user) {
			this.user = user;
		}
	}

	public void checkTextField(FacesContext context, UIComponent component,
			Object value) {
		if (value == null)
			return;
		if (value instanceof String) {
			Pattern p = Pattern.compile("([a-zA-ZüÜöÖäÄß]){3,20}");
			Matcher m = p.matcher((String) value);
			if (!m.matches()) {
				FacesMessage message = Messages.getFacesMessage(context,
						FacesMessage.SEVERITY_ERROR, "onlyLetters");
				context = FacesContext.getCurrentInstance();
				context.addMessage(component.getClientId(), message);
				context.renderResponse();
				return;
			}
		}
	}

}
```


----------

