# Individual grouped Toggle Buttons

**URL:** <https://discourse.holoviz.org/t/individual-grouped-toggle-buttons/3676>\
**Category:** Showcase\
**Tags:** panel\
**Created:** [May 5, 2022, 10:00am UTC](https://discourse.holoviz.org/t/individual-grouped-toggle-buttons/3676 "2022-05-05T10:00:52Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![hyamanieu](https://discourse.holoviz.org/user_avatar/discourse.holoviz.org/hyamanieu/32/251_2.png) [@hyamanieu](https://discourse.holoviz.org/u/hyamanieu)\
**Post date:** [May 5, 2022, 10:00am UTC](https://discourse.holoviz.org/t/individual-grouped-toggle-buttons/3676/1 "2022-05-05T10:00:52Z")

</div>

Using Philipp’s example in [Custom component that is both a Viewer and Reactive](https://discourse.holoviz.org/t/custom-component-that-is-both-a-viewer-and-reactive/3673), I was able to make a group of Toggle buttons with individual design, what the current version of ToggleGroup cannot do.

You can then also manipulate each button `disabled` parameter, see methods `_cannot_be_ok` and `_can_only_be_ok`.

I just wanted to share my work in case someone requires something similar:

![grafik](https://discourse.holoviz.org/uploads/default/original/2X/0/096990dc3fb2e708db62caf98adc6476a4cb121f.png)

```auto
import panel as pn
pn.extension()
import param
OK = 0
NOK = 1
AVG = 2
ASSESSMENTLIST = ('Good!', 'Unsatisfying', 'Average')

class ToggleAssessmmentGroup(pn.widgets.base.CompositeWidget):
    # see https://discourse.holoviz.org/t/custom-component-that-is-both-a-viewer-and-reactive/3673/2

    
    assessment = param.ObjectSelector(default=ASSESSMENTLIST[OK], objects=ASSESSMENTLIST)

    _composite_type = pn.Row

    def __init__ (self, **params):
        self.assessment_ok_btn = pn.widgets.Toggle(
                name=ASSESSMENTLIST[OK], 
                button_type = 'success',
                )
        self.assessment_nok_btn = pn.widgets.Toggle(
            name=ASSESSMENTLIST[NOK], 
            button_type = 'danger',
            )
        self.assessment_avg_btn = pn.widgets.Toggle(
            name=ASSESSMENTLIST[AVG], 
            button_type = 'warning',
            )

        js_callback_check_assessments = """
        if (cb_obj.active) {
        btn1.active = false;
        btn2.active = false;
            };
        """

        self.assessment_ok_btn.jscallback(
            value=js_callback_check_assessments, 
            args={'btn1':self.assessment_nok_btn,
                    'btn2':self.assessment_avg_btn})
        self.assessment_nok_btn.jscallback(
            value=js_callback_check_assessments, 
            args={'btn1':self.assessment_ok_btn,
                    'btn2':self.assessment_avg_btn})
        self.assessment_avg_btn.jscallback(
            value=js_callback_check_assessments, 
            args={'btn1':self.assessment_nok_btn,
                    'btn2':self.assessment_ok_btn})    
        
        def set_assessment_status_cb(event):
            if (event.name == 'value') and (event.new):
                self.assessment = event.obj.name

        self.assessment_ok_btn.param.watch(
            set_assessment_status_cb, 
            'value')
        self.assessment_nok_btn.param.watch(
            set_assessment_status_cb, 
            'value')
        self.assessment_avg_btn.param.watch(
            set_assessment_status_cb, 
            'value')

        super(). __init__ (**params)
        self._composite[:] = [self.assessment_ok_btn, self.assessment_nok_btn, self.assessment_avg_btn]
        self._widget_dict = {obj.name: obj for obj in self._composite}
        self._sync_disabled_param()
        
        self.param.watch(self._sync_widgets,'assessment')

    def _sync_widgets(self, event):
        if self._widget_dict[event.new].disabled:
            err_msg = f'Button "{self.assessment}" is disabled. Previous value is reset: "{event.old}"'
            self.assessment = event.old
            raise ValueError(err_msg)
        else:
            self._widget_dict[self.assessment].value = True

    def _cannot_be_ok(self):
        self.assessment_ok_btn.disabled = True
        self.assessment_nok_btn.disabled = False
        self.assessment_avg_btn.disabled = False

        self.assessment_nok_btn.value = True

    def _can_only_be_ok(self):
        self.assessment_ok_btn.disabled = False
        self.assessment_nok_btn.disabled = True
        self.assessment_avg_btn.disabled = True

        self.assessment_ok_btn.value = True
        
    @param.depends('disabled', watch=True)
    def _sync_disabled_param(self):        
        self.assessment_ok_btn.disabled = self.disabled
        self.assessment_nok_btn.disabled = self.disabled
        self.assessment_avg_btn.disabled = self.disabled
        

a = ToggleAssessmmentGroup(width=300, background='black')

b = pn.pane.Markdown(a.assessment)
a.link(b, assessment='object')

pn.Column("# How did you find our service?", a,b)

```
