Как получить несколько данных из пользовательского компонента в bean-компонент? - PullRequest
1 голос
/ 24 января 2012

У меня есть объект данных с именем DeliveryPeriod, который является контейнером для начальной и конечной даты (сохраняется как String как dd.MM.yyy, приходит из базы данных) и идентификатором другого объекта с именем PlanningPeriod. Этот период доставки должен отображаться в его собственном пользовательском компоненте в формате JSF, например

<myc:deliveryPeriodComponent value="#{backendBean.deliveryPeriod}" />

Я реализую класс DeliveryPeriodComponent, который расширяет UIInput и DeliveryPeriodComponentRenderer, который extendes javax.faces.renderer. Рендеринг работает хорошо, я вижу два элемента календаря и SelectOneMenu, чтобы выбрать период планирования. Но рендеринг данных это еще не все, мне тоже нужно изменить данные. И тут возникает проблема, я понятия не имею, чтобы передать данные внутри моего компонента в бэкэнд-компонент. Метод decode() не знает новых значений, а другие методы никогда не вызываются. Я не знал хитрости, как связать страницу JSF с бином, из учебника (http://jsfatwork.irian.at, я купил книгу) у меня были такие методы, как getValue() и getConverter().

Вот код из компонента:

public class DeliveryPeriodComponent extends UIInput {

public static final String COMPONENT_TYPE = "de.hacon.tps.integrator.web.component.deliveryperiod.DeliveryPeriodComponent";

enum PropertyKeys {
    begin, end, planningPeriod
}

public DeliveryPeriodComponent() {
    setRendererType("de.hacon.tps.integrator.web.component.deliveryperiod.DeliveryPeriodComponent");
}

public String getBegin() {
    return (String) getStateHelper().eval(PropertyKeys.begin, "01.01.2012");
}

public void setBegin(String begin) {
    getStateHelper().put(PropertyKeys.begin, begin);
}

public String getEnd() {
    return (String) getStateHelper().eval(PropertyKeys.end, "31.12.2012");
}

public void setEnd(String end) {
    getStateHelper().put(PropertyKeys.end, end);
}

public int getPlanningPeriod() {
    return (Integer) getStateHelper().eval(PropertyKeys.planningPeriod, 0);
}

public void setPlanningPeriod(int planningPeriod) {
    getStateHelper().put(PropertyKeys.planningPeriod, planningPeriod);
}}

А вот и рендер:

открытый класс DeliveryPeriodComponentRenderer расширяет Renderer {

SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");

@Override
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
    DeliveryPeriodComponent comp = (DeliveryPeriodComponent) component;
    String clientId = comp.getId();
    try {
        encodeInput(context, comp, clientId);
    } catch (ParseException e) {
        e.printStackTrace();
    }
}

private void encodeInput(FacesContext context, DeliveryPeriodComponent comp, String clientId) throws ParseException {
    comp.getChildren().clear();
    DeliveryPeriod value = (DeliveryPeriod) comp.getAttributes().get("value");
    List<PlanningPeriodSubset> pp = (List<PlanningPeriodSubset>) comp.getAttributes().get("periods");

    HtmlPanelGrid pGrid = new HtmlPanelGrid();
    pGrid.setColumns(4);
    Calendar cBegin = new Calendar();
    cBegin.setShowOn("button");
    cBegin.setValue(sdf.parse(value.getStartDate()));
    cBegin.setPattern("dd.MM.yyyy");
    pGrid.getChildren().add(cBegin);
    Calendar cEnd = new Calendar();
    cEnd.setShowOn("button");
    cEnd.setValue(sdf.parse(value.getEndDate()));
    cEnd.setPattern("dd.MM.yyyy");
    pGrid.getChildren().add(cEnd);
    HtmlSelectOneMenu sPlanningPeriod = new HtmlSelectOneMenu();

    Collection<UISelectItem> items = new ArrayList<UISelectItem>();
    for (PlanningPeriodSubset op : pp) {
        UISelectItem item = new UISelectItem();
        item.setItemLabel(op.getName());
        item.setItemValue(op.getId());
        items.add(item);
    }

    sPlanningPeriod.getChildren().addAll(items);
    sPlanningPeriod.setValue(value.getPlanningPeriodId());
    pGrid.getChildren().add(sPlanningPeriod);
    HtmlPanelGrid buttonPanel = new HtmlPanelGrid();
    buttonPanel.setColumns(2);
    Button bDelete = new Button();
    bDelete.setValue(" - ");
    buttonPanel.getChildren().add(bDelete);
    Button bInfo = new Button();
    bInfo.setValue(" i ");
    buttonPanel.getChildren().add(bInfo);
    pGrid.getChildren().add(buttonPanel);
    comp.getChildren().add(pGrid);
}

@Override
public void decode(FacesContext context, UIComponent component) {
    DeliveryPeriodComponent deliveryComponent = (DeliveryPeriodComponent) component;
    DeliveryPeriod deliveryPeriod = new DeliveryPeriod();
    deliveryPeriod.setStartDate(deliveryComponent.getBegin());
    deliveryPeriod.setEndDate(deliveryComponent.getEnd());
    deliveryPeriod.setPlanningPeriodId(deliveryComponent.getPlanningPeriod());

    // Map<String, String> params = context.getExternalContext().getRequestParameterMap();
    // String clientId = component.getClientId();
    // String value = params.get(clientId);
    // ((UIInput) component).setSubmittedValue(value);
}

@Override
public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue)
        throws ConverterException {
    Converter converter = getConverter(context, (DeliveryPeriodComponent) component);
    if (converter != null) {
        return converter.getAsObject(context, component, (String) submittedValue);
    } else {
        return submittedValue;
    }
}

private Object getValue(FacesContext context, DeliveryPeriodComponent comp) {
    Object submittedValue = comp.getSubmittedValue();
    if (submittedValue != null) {
        return submittedValue;
    }
    Object begin = comp.getBegin();
    Object end = comp.getEnd();
    Object planningPeriod = comp.getPlanningPeriod();
    DeliveryPeriod period = new DeliveryPeriod();
    period.setStartDate((String) begin);
    period.setEndDate((String) end);
    period.setPlanningPeriodId((Integer) planningPeriod);
    Converter converter = this.getConverter(context, comp);
    if (converter != null) {
        return converter.getAsString(context, comp, period);
    } else if (period != null) {
        return period.toString();
    } else {
        return "";
    }
}

private Converter getConverter(FacesContext context, DeliveryPeriodComponent comp) {
    Converter conv = ((UIInput) comp).getConverter();
    if (conv != null) {
        ValueExpression exp = comp.getValueExpression("value");
        if (exp == null) {
            return null;
        } else {
            Class valueType = exp.getType(context.getELContext());
            if (valueType == null) {
                return null;
            } else {
                return context.getApplication().createConverter(valueType);
            }
        }
    }
    return null;
}}

Может быть, это тривиальная проблема, я не профессионал в JSF и все еще учусь. И очень сложно писать свои собственные компоненты, когда вы почти не понимаете основ :-( Все еще изучаете новые вещи каждый день. Спасибо за вашу помощь!

(Я нашел много пользовательских компонентов с примерами, такими как поля ввода custum, эти компоненты хорошо работают и передают свои данные. К сожалению, я ничего не нашел в пользовательских компонентах, которые содержат более одного поля ввода или сделали что-то отличное от существующих элементов JSF )

1 Ответ

0 голосов
/ 30 января 2012

На странице Xhtml Позвоните своему составителю с помощью

<h:commandButton id="add" value="Add More" styleClass="input_right_cor" type="button">
                    <f:ajax execute="@this" listener="#{templateSearchHandler.AddRow}"  />
                </h:commandButton> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...