How to Conditionally Render Plain HTML Elements Like <Div>S

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



Leave a reply



Submit