Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Rapster committed Aug 24, 2024
1 parent 75e5c59 commit baec44f
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 127 deletions.
26 changes: 10 additions & 16 deletions primefaces/src/main/java/org/primefaces/component/api/UIColumn.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -40,7 +39,7 @@

import org.primefaces.component.celleditor.CellEditor;
import org.primefaces.model.MatchMode;
import org.primefaces.util.ComponentTraversalUtils;
import org.primefaces.util.EditableValueHolderState;
import org.primefaces.util.FacetUtils;
import org.primefaces.util.LangUtils;

Expand Down Expand Up @@ -249,23 +248,18 @@ default String getColumnKey(UIComponent parent, int rowIndex) {

Object getConverter();

default EditableValueHolder getFilterValueHolder() {
default EditableValueHolderState getFilterValueHolder(FacesContext context) {
UIComponent filterFacet = getFacet("filter");
return ComponentTraversalUtils.firstChildRenderedOrSelf(EditableValueHolder.class, filterFacet);
}

default Object getFilterValueFromValueHolder(FacesContext context) {
UIComponent filterFacet = getFacet("filter");
if (filterFacet == null) {
return null;
if (filterFacet != null) {
EditableValueHolderState state = new EditableValueHolderState();
FacetUtils.invokeOnEditableValueHolder(context, filterFacet, (fc, target) -> {
state.setComponent((EditableValueHolder) target);
state.setValue(((EditableValueHolder) target).getValue());
});
return state;
}
AtomicReference<Object> filterValue = new AtomicReference<>(null);

FacetUtils.invokeOnEditableValueHolder(context, filterFacet, (ctx, component) -> {
filterValue.set(((EditableValueHolder) component).getValue());
});

return filterValue.get();
return null;
}

default void setFilterValueToValueHolder(Object value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.component.ValueHolder;
Expand All @@ -45,10 +44,7 @@
import org.primefaces.model.ColumnMeta;
import org.primefaces.model.FilterMeta;
import org.primefaces.model.SortMeta;
import org.primefaces.util.ComponentUtils;
import org.primefaces.util.FacetUtils;
import org.primefaces.util.LangUtils;
import org.primefaces.util.LocaleUtils;
import org.primefaces.util.*;

public interface UITable<T extends UITableState> extends ColumnAware, MultiViewStateAware<T> {

Expand Down Expand Up @@ -197,11 +193,11 @@ default void updateFilterByValuesWithFilterRequest(FacesContext context, Map<Str
((DynamicColumn) column).applyModel();
}

EditableValueHolder hasCustomFilter = column.getFilterValueHolder();
EditableValueHolderState editableValueHolderState = column.getFilterValueHolder(context);

Object filterValue;
if (hasCustomFilter != null) {
filterValue = column.getFilterValueFromValueHolder(context);
if (editableValueHolderState != null) {
filterValue = editableValueHolderState.getValue();
}
else {
String valueHolderClientId = column instanceof DynamicColumn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,74 +62,16 @@ public void encodeEnd(FacesContext context, UIComponent component) throws IOExce
.add(ComponentUtils.isRTL(context, label), OutputLabel.RTL_CLASS)
.add(label.getStyleClass());

final EditableValueHolderState state = new EditableValueHolderState();
EditableValueHolderState forState = null;

final String indicateRequired = label.getIndicateRequired();
boolean isAuto = "auto".equals(indicateRequired) || "autoSkipDisabled".equals(indicateRequired);

String _for = label.getFor();
if (!isValueBlank(_for)) {
ContextCallback callback = (ctxt, target) -> {
if (target instanceof InputHolder) {
InputHolder inputHolder = ((InputHolder) target);
state.setClientId(inputHolder.getInputClientId());

inputHolder.setLabelledBy(clientId);
}
else {
state.setClientId(target.getClientId(ctxt));
}

if (target instanceof UIInput) {
UIInput input = (UIInput) target;

if (value != null && (input.getAttributes().get("label") == null || input.getValueExpression("label") == null)) {
ValueExpression ve = label.getValueExpression("value");

if (ve != null) {
input.setValueExpression("label", ve);
}
else {
String labelString = value;
char separatorChar = UINamingContainer.getSeparatorChar(ctxt);
int separatorCharPos = labelString.lastIndexOf(separatorChar);

if (separatorCharPos != -1) {
labelString = labelString.substring(0, separatorCharPos);
}

input.getAttributes().put("label", labelString);
}
}

if (!input.isValid()) {
styleClassBuilder.add("ui-state-error");
}

if (isAuto) {
boolean disabled = false;
if ("autoSkipDisabled".equals(indicateRequired)) {
disabled = ComponentUtils.isDisabledOrReadonly(input);
}

if (disabled) {
state.setRequired(false);
}
else {
state.setRequired(input.isRequired());
// fallback if required=false
if (!state.isRequired()) {
PrimeApplicationContext applicationContext = PrimeApplicationContext.getCurrentInstance(ctxt);
if (applicationContext.getConfig().isBeanValidationEnabled() && isBeanValidationDefined(input, ctxt)) {
state.setRequired(true);
}
}
}
}
}
};

UIComponent forComponent = SearchExpressionUtils.contextlessResolveComponent(context, label, _for);
ContextCallbackFor callback = new ContextCallbackFor(clientId, indicateRequired, isAuto, label, styleClassBuilder, value);
forState = callback.getState();

if (CompositeUtils.isComposite(forComponent)) {
CompositeUtils.invokeOnDeepestEditableValueHolder(context, forComponent, callback);
Expand All @@ -140,7 +82,7 @@ public void encodeEnd(FacesContext context, UIComponent component) throws IOExce
}

boolean withRequiredIndicator = "true".equals(indicateRequired)
|| (isAuto && !isValueBlank(_for) && state.isRequired());
|| (isAuto && forState != null && forState.isRequired());
if (withRequiredIndicator) {
styleClassBuilder.add("ui-required");
}
Expand All @@ -153,7 +95,7 @@ public void encodeEnd(FacesContext context, UIComponent component) throws IOExce
renderRTLDirection(context, label);

if (!isValueBlank(_for)) {
writer.writeAttribute("for", state.getClientId(), "for");
writer.writeAttribute("for", forState.getClientId(), "for");
}

if (value != null) {
Expand Down Expand Up @@ -234,4 +176,89 @@ public void encodeChildren(FacesContext context, UIComponent component) throws I
public boolean getRendersChildren() {
return true;
}

private class ContextCallbackFor implements ContextCallback {

private final EditableValueHolderState state = new EditableValueHolderState();
private final UIComponent label;
private final String indicateRequired;
private final String clientId;
private final String value;
private final StyleClassBuilder styleClassBuilder;
private final boolean isAuto;

public ContextCallbackFor(String clientId, String indicateRequired, boolean isAuto, UIComponent label,
StyleClassBuilder styleClassBuilder, String value) {
this.clientId = clientId;
this.indicateRequired = indicateRequired;
this.isAuto = isAuto;
this.label = label;
this.styleClassBuilder = styleClassBuilder;
this.value = value;
}

@Override
public void invokeContextCallback(FacesContext context, UIComponent target) {
if (target instanceof InputHolder) {
InputHolder inputHolder = ((InputHolder) target);
state.setClientId(inputHolder.getInputClientId());
inputHolder.setLabelledBy(clientId);
}
else {
state.setClientId(target.getClientId(context));
}

if (target instanceof UIInput) {
UIInput input = (UIInput) target;

if (value != null && (input.getAttributes().get("label") == null || input.getValueExpression("label") == null)) {
ValueExpression ve = label.getValueExpression("value");

if (ve != null) {
input.setValueExpression("label", ve);
}
else {
String labelString = value;
char separatorChar = UINamingContainer.getSeparatorChar(context);
int separatorCharPos = labelString.lastIndexOf(separatorChar);

if (separatorCharPos != -1) {
labelString = labelString.substring(0, separatorCharPos);
}

input.getAttributes().put("label", labelString);
}
}

if (!input.isValid()) {
styleClassBuilder.add("ui-state-error");
}

if (isAuto) {
boolean disabled = false;
if ("autoSkipDisabled".equals(indicateRequired)) {
disabled = ComponentUtils.isDisabledOrReadonly(input);
}

if (disabled) {
state.setRequired(false);
}
else {
state.setRequired(input.isRequired());
// fallback if required=false
if (!state.isRequired()) {
PrimeApplicationContext applicationContext = PrimeApplicationContext.getCurrentInstance(context);
if (applicationContext.getConfig().isBeanValidationEnabled() && isBeanValidationDefined(input, context)) {
state.setRequired(true);
}
}
}
}
}
}

public EditableValueHolderState getState() {
return state;
}
}
}
26 changes: 11 additions & 15 deletions primefaces/src/main/java/org/primefaces/event/CellEditEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@
*/
package org.primefaces.event;

import java.util.ArrayList;
import java.util.List;

import javax.faces.FacesException;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.Behavior;
import javax.faces.context.FacesContext;

import org.primefaces.component.api.DynamicColumn;
import org.primefaces.component.api.UIColumn;
import org.primefaces.component.api.UIData;
Expand All @@ -32,15 +41,6 @@
import org.primefaces.component.treetable.TreeTable;
import org.primefaces.util.FacetUtils;

import javax.faces.FacesException;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.Behavior;
import javax.faces.context.FacesContext;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

public class CellEditEvent<T> extends AbstractAjaxBehaviorEvent {

private static final long serialVersionUID = 1L;
Expand Down Expand Up @@ -159,21 +159,17 @@ else if (source instanceof UITree) {
if (child instanceof CellEditor) {
UIComponent inputFacet = child.getFacet("input");

AtomicBoolean invoked = new AtomicBoolean(false);
List<Object> values = new ArrayList<>(1);

FacetUtils.invokeOnEditableValueHolder(FacesContext.getCurrentInstance(), inputFacet, (ctx, component) -> {
values.add(((EditableValueHolder) component).getValue());
invoked.set(true);
});

if (!invoked.get()) {
if (values.isEmpty()) {
throw new FacesException("No ValueHolder found inside the 'input' facet of the CellEditor!");
}

if (!values.isEmpty()) {
value = values.size() > 1 ? (T) values : (T) values.get(0);
}
value = values.size() > 1 ? (T) values : (T) values.get(0);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.primefaces.model.filter.FilterConstraints;
import org.primefaces.model.filter.FunctionFilterConstraint;
import org.primefaces.model.filter.GlobalFilterConstraint;
import org.primefaces.util.EditableValueHolderState;
import org.primefaces.util.LangUtils;

public class FilterMeta implements Serializable {
Expand Down Expand Up @@ -100,7 +101,10 @@ else if (filterByVE == null) {

Object filterValue = column.getFilterValue();
if (filterValue == null) {
filterValue = column.getFilterValueFromValueHolder(context);
EditableValueHolderState state = column.getFilterValueHolder(context);
if (state != null) {
filterValue = state.getValue();
}
}

return new FilterMeta(column.getColumnKey(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,17 +183,6 @@ public static UIComponent closestNamingContainer(UIComponent component) {
return (UIComponent) closest(NamingContainer.class, component);
}

public static <T> T firstChildRenderedOrSelf(Class<T> childType, UIComponent base) {
if (base == null || !base.isRendered()) {
return null;
}
else if (childType.isInstance(base)) {
return (T) base;
}

return firstChildRendered(childType, base);
}

public static <T> T firstChildRendered(Class<T> childType, UIComponent base) {
if (base == null || !base.isRendered()) {
return null;
Expand Down
Loading

0 comments on commit baec44f

Please sign in to comment.