Set background color of every individual checkbox of p:selectManyCheckbox
Asked Answered
G

4

9

I am using this http://www.primefaces.org/showcase-labs/ui/selectManyCheckbox.jsf primefaces componenent to get dynamic booleanCheckboxes values

<p:selectManyCheckbox value="#{bean.selectedMovies}"  
            layout="pageDirection">  
            <f:selectItems value="#{bean.movies}" />  
        </p:selectManyCheckbox> 

I need to apply different colors to all boolean checkboxes as shown in below image

if id=1 then color will be red if id=2 then color will be orange and so on.

As we know these are the dynamic values in movies, so how can I set background-color to these dynamic checkboxes from backing bean ?

I tried to apply style to selectManyCheckbox but it applies as a background color to whole selectManyCheckbox panel.

so how should I set color from backing bean to selectManyCheckbox values dynamically ?

enter image description here

Guessrope answered 14/9, 2012 at 7:32 Comment(1)
Let me know if anybody needs more clarification...Guessrope
R
4

May be Doable with Pure CSS3

Depending on your actual requirements. Assuming the same html structure for the final check boxes is the default structure as in the example you link to, then the following should be a pure css3 way to accomplish it.

Note that this method does not specifically tie the color to a particular movie/id, it always sets the first movie to red, the second to orange, etc. It also has a practical limitation. If you plan to list 100 movies, each with a unique individual color, then this is not the method for you.

But if you are listing a small set (10 max?), or you don't mind if the colors repeat after a certain small sampling, then this may well be your best choice.

Here's a fiddle showing both of the following

Small Set

.ui-selectmanycheckbox tr:nth-of-type(1) .ui-state-default {
    background-color: red;
}

.ui-selectmanycheckbox tr:nth-of-type(2) .ui-state-default {
    background-color: orange;
}

.ui-selectmanycheckbox tr:nth-of-type(3) .ui-state-default {
    background-color: red;
}

.ui-selectmanycheckbox tr:nth-of-type(4) .ui-state-default {
    background-color: orange;
}

Repeating 4-Colors

.ui-selectmanycheckbox tr:nth-of-type(4n+1) .ui-state-default {
    background-color: red;
}

.ui-selectmanycheckbox tr:nth-of-type(4n+2) .ui-state-default {
    background-color: orange;
}

.ui-selectmanycheckbox tr:nth-of-type(4n+3) .ui-state-default {
    background-color: green;
}

.ui-selectmanycheckbox tr:nth-of-type(4n+4) .ui-state-default {
    background-color: blue;
}
Ribeiro answered 23/9, 2012 at 18:4 Comment(0)
L
4

This isn't possible with a standard <p:selectManyCheckbox>, at least not with this kind of dynamics. If it were static values, you could just have used the CSS3 nth-child() selector for this. With dynamic values in a <p:selectManyCheckbox>, you'd basically need to override its renderer (which is not a trivial job) or to post a feature request (which might take longer than you want).

Your best bet is using <ui:repeat> or <h:dataTable> instead wherein you render a single <p:selectBooleanCheckbox> on a per-row basis. This allows you specifying a styleClass on a per-checkbox basis. This only also requires a technical change in how the selectedMovies property is populated.

Here's a concrete kickoff example with <h:dataTable> (note: the <p:selectManyCheckbox> itself also generates a <table>, so layout-technically there's not so much difference, you can always choose for <ui:repeat> if the table bothers you semantically):

<h:dataTable value="#{bean.movies}" var="movie" styleClass="ui-selectmanycheckbox ui-widget">
    <h:column>
        <p:selectBooleanCheckbox id="checkbox" converter="javax.faces.Boolean"
            value="#{bean.checkedMovieIds[movie.id]}" styleClass="#{movie.type}" />
    </h:column>
    <h:column>
        <p:outputLabel for="checkbox" value="#{movie.title}" />
    </h:column>
</h:dataTable>

<p:commandButton value="Submit" actionListener="#{bean.collectMovies}" action="#{bean.submit}" />

Notes:

  • The <h:dataTable styleClass> uses exactly the same CSS as <p:selectManyCheckbox>, so the checkbox table look'n'feel is exactly the same.
  • The converter="javax.faces.Boolean" is (actually, to my surprise) mandatory, because it would otherwise set checked values true and false as String instead of Boolean; this problem doesn't exist in <h:selectBooleanCheckbox>, perhaps a PF bug?
  • The styleClass="#{movie.type}" made in this particular use case more sense than styleClass="#{movie.id}", because it seems a ridiculuous task to specify a separate style class for every individual "id" value which usually represents an unique auto-assigned DB identifier; you can always change it in your actual code if you want.
  • The actionListener does the job of collecting the selectedMovies before the actual action method. You can of course also do the job in the actual action method, but this it's then not so cleanly separated anymore.

The backing bean look like this (the checkedMovieIds assumes that Movie has a Long id property):

private List<Movie> movies;
private Map<Long, Boolean> checkedMovieIds;
private List<Movie> selectedMovies;

@PostConstruct
public void init() {
    movies = populateItSomehow();
    checkedMovieIds = new HashMap<Long, Boolean>();
}

public void collectMovies(ActionEvent event) {
    selectedMovies = new ArrayList<Movie>();
    for (Movie movie : movies) {
        if (checkedMovieIds.get(movie.getId())) {
            selectedMovies.add(movie);
        }
    }
}

public void submit() {
    System.out.println(selectedMovies);
    // ...
}

// +getters (note: no setters necessary for all those three properties)

Assuming that #{movie.type} can have the values action, comedy, fantasy and horror (it's by the way a perfect enum type candidate), then you can style the individual checkboxes as follows:

.action .ui-chkbox-box {
    background-color: red;
}

.comedy .ui-chkbox-box {
    background-color: orange;
}

.fantasy .ui-chkbox-box {
    background-color: green;
}

.horror .ui-chkbox-box {
    background-color: blue;
}
Lorrielorrimer answered 17/9, 2012 at 13:36 Comment(0)
R
4

May be Doable with Pure CSS3

Depending on your actual requirements. Assuming the same html structure for the final check boxes is the default structure as in the example you link to, then the following should be a pure css3 way to accomplish it.

Note that this method does not specifically tie the color to a particular movie/id, it always sets the first movie to red, the second to orange, etc. It also has a practical limitation. If you plan to list 100 movies, each with a unique individual color, then this is not the method for you.

But if you are listing a small set (10 max?), or you don't mind if the colors repeat after a certain small sampling, then this may well be your best choice.

Here's a fiddle showing both of the following

Small Set

.ui-selectmanycheckbox tr:nth-of-type(1) .ui-state-default {
    background-color: red;
}

.ui-selectmanycheckbox tr:nth-of-type(2) .ui-state-default {
    background-color: orange;
}

.ui-selectmanycheckbox tr:nth-of-type(3) .ui-state-default {
    background-color: red;
}

.ui-selectmanycheckbox tr:nth-of-type(4) .ui-state-default {
    background-color: orange;
}

Repeating 4-Colors

.ui-selectmanycheckbox tr:nth-of-type(4n+1) .ui-state-default {
    background-color: red;
}

.ui-selectmanycheckbox tr:nth-of-type(4n+2) .ui-state-default {
    background-color: orange;
}

.ui-selectmanycheckbox tr:nth-of-type(4n+3) .ui-state-default {
    background-color: green;
}

.ui-selectmanycheckbox tr:nth-of-type(4n+4) .ui-state-default {
    background-color: blue;
}
Ribeiro answered 23/9, 2012 at 18:4 Comment(0)
C
0

I know this solution is a little bit hacky, but it works :)

Xhtml file :

<p:selectManyCheckbox binding="#{requestScope.movieSelect}" layout="pageDirection">
    <f:selectItems value="#{bean.movies}" />
</p:selectManyCheckbox>

<script>
(function() {
    var selectName = '#{requestScope.movieSelect.clientId}';
    var kids = jQuery("input[id*="+selectName+"]");
    var index = 0;

    <ui:repeat value="#{bean.movies}" var="movie">
        jQuery(kids[index++]).parent().next().css('background-color', '#{movie.description}');
    </ui:repeat>
}());
</script>

Backing bean :

public class Bean {

    private List<SelectItem> movies = Arrays.asList(
            new SelectItem("Scarface", "Scarface", "green"),
            new SelectItem("Goodfellas", "Goodfellas", "red"),
            new SelectItem("Godfather", "Godfather", "blue"),
            new SelectItem("Carlito's Way", "Carlito's Way", "yellow"));

    public List<SelectItem> getMovies() {
        return movies;
    }
}

Css file :

.ui-chkbox-box {
    background-image : none;
}

p.s. : the css file may not be neccessary.

Carabao answered 17/9, 2012 at 20:6 Comment(0)
D
0

not sure what your browser targets are, but why not use attribute selectors?

ui-selectmanycheckbox input[value=1] {
    color: red;
}

That's just the general idea... I'm not familiar with those controls, but the documentation makes it look like you should be able to make this work...

Dittman answered 17/9, 2012 at 20:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.