【问题标题】:How can I dynamically generate a CSS for a JSF custom component如何为 JSF 自定义组件动态生成 CSS
【发布时间】:2013-12-18 00:23:53
【问题描述】:

我正在开发一个执行“响应式”多列显示的 JSF 自定义组件。

它使用“CSS 多列布局模块”(http://www.w3.org/TR/css3-multicol/)(法语教程:http://www.alsacreations.com/tuto/lire/1557-les-multicolonnes-en-css3.html)。

我实际上有以下解决方案,它有效:

组件类:

@Log4j
@FacesComponent(ResponsiveMultiColumnsTable.SENAT_COMPONENT_TYPE)
@ResourceDependency(library="senat",name="senat-columns.css")
public class ResponsiveMultiColumnsTable extends UIData {
    public static final String SENAT_COMPONENT_FAMILY = "fr.senat.faces.components";
    public static final String SENAT_COMPONENT_TYPE = SENAT_COMPONENT_FAMILY + ".ResponsiveMultiColumnsTable";
    public static final String DEFAULT_RENDERER = SENAT_COMPONENT_FAMILY + ".ResponsiveMultiColumnsPanelRenderer";

    private enum PropertyKeys { style, styleClass }

    public ResponsiveMultiColumnsTable() {
      setRendererType(DEFAULT_RENDERER);
    }

    @Override
    public boolean getRendersChildren()
    {
        return true;
    }

    public String getStyle() {
        return (String) getStateHelper().eval(PropertyKeys.style);
    }

    public void setStyle(String param) {
        getStateHelper().put(PropertyKeys.style, param);
    }

    public String getStyleClass() {
        return (String) getStateHelper().eval(PropertyKeys.styleClass);
    }

    public void setStyleClass(String param) {
        getStateHelper().put(PropertyKeys.styleClass, param);
    }

}

渲染器类:

@FacesRenderer(componentFamily = ResponsiveMultiColumnsTable.COMPONENT_FAMILY, rendererType = ResponsiveMultiColumnsTable.DEFAULT_RENDERER)
public class ResponsiveMultiColumnsTableRenderer extends CoreRenderer {

    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
        ResponsiveMultiColumnsTable detail = (ResponsiveMultiColumnsTable) component;
        ResponseWriter writer = context.getResponseWriter();
        String clientId = detail.getClientId(context);
        String style = detail.getStyle();
        String styleClass = detail.getStyleClass();

        writer.startElement("div", detail);
        writer.writeAttribute("id", clientId, "id");
        String extStyleClass = "senat-details-columns";
        if (styleClass != null) {
            extStyleClass += " " + styleClass;
        }
        writer.writeAttribute("class", "senat-details-columns " + extStyleClass, "styleClass");
        if ((style != null) && !style.isEmpty()) {
            writer.writeAttribute("style", style, "style");
        }
    }

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        writer.endElement("div");
    }

    @Override
    public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        ResponsiveMultiColumnsTable grid = (ResponsiveMultiColumnsTable) component;

        int rowIndex = grid.getFirst();
        int rows = grid.getRows();
        int itemsToRender = rows != 0 ? rows : grid.getRowCount();

        for(int i = rowIndex ; i < itemsToRender ; i++) {
            grid.setRowIndex(i);
            if(!grid.isRowAvailable()) {
                break;
            }

            writer.startElement("div", null);

            renderChildren(context, grid);

            writer.endElement("div");
        }

    }
}

taglib 中的组件声明:

    <tag>
    <description>
        <![CDATA[
                    *** À compléter ***
        ]]>
    </description>
    <tag-name>responsiveMultiColumnsTable</tag-name>
            <component>
                <component-type>fr.senat.faces.components.ResponsiveMultiColumnsTable</component-type>
            </component>

    <attribute>
                <description>Liste à afficher
                </description>
                <name>value</name>
                <required>true</required>
                <type>java.util.List</type>
    </attribute>
            <attribute>
                <description>Nom de la variable d'itération</description>
                <name>var</name>
                <required>true</required>
                <type>java.lang.String</type>
    </attribute>
    <attribute>
                <description>Élément de style à ajouter</description>
                <name>style</name>
                <required>false</required>
                <type>java.lang.String</type>
    </attribute>
    <attribute>
                <description>Classe à ajouter</description>
                <name>styleClass</name>
                <required>false</required>
                <type>java.lang.String</type>
    </attribute>
</tag>

样式表:

.senat-details-columns {
    -webkit-columns: 3;
    -moz-columns: 3;
    columns: 3;
}

@media (max-width: 1024px) {
    .senat-details-columns {
        -webkit-columns: 2;
        -moz-columns: 2;
        columns: 2;
    }
}

@media (max-width: 640px) {
    .senat-details-columns {
        -webkit-columns: 1;
        -moz-columns: 1;
        columns: 1;
    }
}

我希望能够指示数据,例如在哪种分辨率下使用哪个列数。一种方法是动态生成样式表片段,然后包含它。

基本动态样式表如下所示:

.#{dynamic-style} {
    -webkit-columns: #{max-col-count};
    -moz-columns: #{max-col-count};
    columns: #{max-col-count};
}

@media (max-width: #{max-middle-res}px) {
    .#{dynamic-style} {
        -webkit-columns: #{middle-col-count};
        -moz-columns: #{middle-col-count};
        columns: #{middle-col-count};
    }
}

@media (max-width: #{max-min-res}px) {
    .#{dynamic-style} {
        -webkit-columns: #{min-col-count};
        -moz-columns: #{middle-col-count};
        columns: #{middle-col-count};
    }
}

如何动态处理并包含它?

我看到的问题是我可以多次使用具有不同参数的同一个样式表。如果只有一种用途,只需在样式表中包含 EL 表达式即可。

另一种解决方案是在组件之前添加样式,但这对我来说有点难看。

【问题讨论】:

  • JSF 是一个在服务器端动态生成客户端代码的工具。考虑到该分辨率是特定于客户端的,因此很难在服务器端使用它。我认为你能做到的最好的就是在客户端设备本身之间有所不同(考虑一些框架,比如Spring Mobile)。
  • @XtremeBiker 或使用已经简化这项工作的前端框架,例如Bootstrap
  • 这些变量应该是基于请求的还是会话范围的或应用程序范围的?您打算在哪里/如何准备/设置这些 EL 变量?
  • @BalusC 我会将它们作为自定义组件的参数传递。类似于 。而且我想在同一页面上使用具有不同参数的相同组件。
  • @XtremeBiker & Luiggi 的目标是获得编译后的 java 代码的好处。我当然可以使用纯 HTML/CSS3 获得预期的结果,但对我来说似乎不太容易维护。

标签: html css jsf jsf-2


【解决方案1】:

您可以简单地将 EL 表达式放入 .ccs 文件中,JSF 将像处理 .xhtml 文件一样处理它们。

您需要将它们包含在 &lt;h:outputStylesheet 中或直接从 HTML 中使用 /javax.faces.resource/foo.css?ln=bar

【讨论】:

  • 如果数据是基于请求的,那将不起作用。显然,CSS 文件是在与具有特定组件的 JSF 页面完全不同的 HTTP 请求中请求的。当我在问题的 cmets 中询问时,OP 并不清楚这一点,因此不可能给出有效的答案。
猜你喜欢
  • 2011-12-08
  • 1970-01-01
  • 2020-08-04
  • 1970-01-01
  • 1970-01-01
  • 2014-10-14
  • 2010-09-07
  • 2017-11-07
  • 2012-06-21
相关资源
最近更新 更多