How to conditionally render plain HTML elements like div s?
The right JSF component to represent a HTML <div>
element is the <h:panelGroup>
with the layout
attribute set to block
. So, this should do:
<h:panelGroup layout="block" ... rendered="#{someCondition}">
...
</h:panelGroup>
Alternatively, wrap it in an <ui:fragment>
:
<ui:fragment rendered="#{someCondition}">
<div>
...
</div>
</ui:fragment>
Or when you're already on JSF 2.2+, make it a passthrough element:
<div jsf:rendered="#{someCondition}">
</div>
Do note that when you'd like to ajax-update a conditionally rendered component, then you should be ajax-updating its parent component instead.
See also:
- Alternative to ui:fragment in JSF
- Conditional rendering of non-JSF components (plain vanilla HTML and template text)
- Ajax update/render does not work on a component which has rendered attribute
- Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
- Is it possible to update non-JSF components (plain HTML) with JSF ajax?
Conditionally render a div based on value of h:outputText
You need to use binding
attribute to put the UIComponent
instance in the EL scope. The id
attribute doesn't do that, on contrary to what you expected.
<h:outputText binding="#{alarmCriticality}" ... />
And then you need to use UIOutput#getValue()
to obtain its value
attribute.
<c:if test="#{alarmCriticality.value == 'Alarm *'}">
That said, you'd better use rendered
attribute here, particularly if #{summary}
represents the currently iterated item of a JSF iterating component like <ui:repeat>
or <h:dataTable>
.
<h:panelGroup layout="block" styleClass="alarm1"
rendered="#{alarmCriticality.value == 'Alarm *'}" />
See also:
- How does the 'binding' attribute work in JSF? When and how should it be used?
- How to conditionally render plain HTML elements like <div>s?
- JSTL in JSF2 Facelets... makes sense?
Unrelated to the concrete problem. It's strange to see the conditional rendering depend on localized text. What if you change the locale and/or the localized text? This is very brittle. You'd better check the bundle key instead.
<h:outputText value="#{msg[summary.criticality.key]}" />
<h:panelGroup layout="block" styleClass="alarm1"
rendered="#{summary.criticality.key == 'some.alarm.key'}" />
This way you also don't need to bind the output text anymore.
How to render HTML conditionally in javascript
The most simple and best readable answer will be to use an if
block:
var object = { required: true};var template = '';
template += '<div class="form-group col-lg-12">';template += '<label class="control-label"' + (object.required ? ' required>' : '>');
document.body.innerText = template;
HTL conditional rendering while not affecting nested html
This is exactly what data-sly-unwrap
is for:
<A data-sly-unwrap="${!properties.value}">
<B>my content</B>
</A>
(note the inverted condition wrt your example because when data-sly-unwrap evaluates to true, it will unwrap the element, i.e. only display the contents).
How to conditionally group HTML tags in React
You can do this with a simple loop, which to me is by far the clearest way; see comments:
const {menuIds} = category;
const elements = [];
// Include every 5th element directly, including the 0th one;
// group the (up to) four following it
let index = 0;
while (index < menuIds.length) {
// Use this entry directly, note we increment index after using it
// in the `TemplateMenu`
const {menuId} = menuIds[index];
elements.push(
<TemplateMenu
index={index++}
key={menuId}
menu={this.props.menus[menuId]}
menuLayout={category.menu_layout}
/>
);
// Follow it with up to four in a `<div class="MenuRight">`
const following = menuIds.slice(index, index + 4);
if (following.length) {
// Note we increment `index` as we go
elements.push(
<div className="MenuRight">
{following.map(({menuId}) => (
<TemplateMenu
index={index++}
key={menuId}
menu={this.props.menus[menuId]}
menuLayout={category.menu_layout}
/>
))}
</div>
);
}
}
// ...use {elements}...
Live Example:
const {useState} = React;
const TemplateMenu = ({index, menu, menuLayout}) => <div className="TemplateMenu">{menu}</div>;
class Example extends React.Component {
render() {
const category = {
menuIds: [
{menuId: 0},
{menuId: 1},
{menuId: 2},
{menuId: 3},
{menuId: 4},
{menuId: 5},
{menuId: 6},
{menuId: 7},
{menuId: 8},
{menuId: 9},
],
menu_layout: "example",
};
const {menuIds} = category;
const elements = [];
// Include every 5th element directly, including the 0th one;
// group the (up to) four following it
let index = 0;
while (index < menuIds.length) {
// Use this entry directly, note we increment index after using it
// in the `TemplateMenu`
const {menuId} = menuIds[index];
elements.push(
<TemplateMenu
index={index++}
key={menuId}
menu={this.props.menus[menuId]}
menuLayout={category.menu_layout}
/>
);
// Follow it with up to four in a `<div class="MenuRight">`
const following = menuIds.slice(index, index + 4);
if (following.length) {
// Note we increment `index` as we go
elements.push(
<div className="MenuRight">
{following.map(({menuId}) => (
<TemplateMenu
index={index++}
key={menuId}
menu={this.props.menus[menuId]}
menuLayout={category.menu_layout}
/>
))}
</div>
);
}
}
// ...use {elements}...
return <div>{elements}</div>;
}
};
const menus = [
"Menu 0",
"Menu 1",
"Menu 2",
"Menu 3",
"Menu 4",
"Menu 5",
"Menu 6",
"Menu 7",
"Menu 8",
"Menu 9",
];
ReactDOM.render(
<Example menus={menus} />,
document.getElementById("root")
);
.TemplateMenu {
border: 1px solid green;
margin: 4px;
}
.MenuRight {
margin: 4px;
padding: 4px;
border: 1px solid red;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
Manipulate an element that is conditionally rendered
scope.$watch('$viewContentLoaded', functionToManipulateDom)
Conditional rendering of non-JSF components (plain vanilla HTML and template text)
I cannot use
<h:panelGroup>
as it will render to<span>
or<div>
Apparently you didn't test it carefully. The <h:panelGroup>
won't render anything if you don't specify attributes which should end up in the client side, like layout
, id
, styleClass
, etc.
Thus, this should technically perfectly work fine.
<h:panelGroup rendered="#{negotiator.maySend}">
<tr> my tr stuff </tr>
</h:panelGroup>
However, better for the main purpose would be to use <ui:fragment>
.
<ui:fragment rendered="#{negotiator.maySend}">
<tr> my tr stuff </tr>
</ui:fragment>
This is by the way also possible with <f:verbatim>
, but this is deprecated since JSF 2.0 as it's designed specifically for usage in JSP.
See also:
- Alternative to ui:fragment in JSF
- Conditionally displaying JSF components
- How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
- Ajax update/render does not work on a component which has rendered attribute
Related Topics
Transform: Translate(-50%, -50%)
HTML Select Box Options on Hover
Why Are Button's Discouraged from Navigation
Using Display Inline-Block Columns Move Down
How to Put Text Over Images in HTML
Youtube Embedded Video: Autoplay Feature Not Working in Iphone
Problem with <Select> and :After with CSS in Webkit
Using HTML5, How to Use Contenteditable Fields in a Form Submission
How to Make a Display:Flex Container Expand Horizontally with Its Wrapped Contents
Why Should I Prepend My Custom Attributes with "Data-"
How to Run an External Program, E.G. Notepad, Using Hyperlink
Send HTML Mail Using Android Intent
:Nth-Child(Even/Odd) Selector with Class
Best Way to Synchronize Local HTML5 Db (Websql Storage, SQLite) with a Server (2 Way Sync)
Is Type="Text/Css" Necessary in a ≪Link≫ Tag
How to Center an Element in the Middle of the Browser Window