Is there a way to disable "Next" in pipeline if a value is not selected/entered?

For example, if I have a param.ListObject; I want the user to at least click something before allowing them to advance to the next stage.


import glob

class Stage1(param.Parameterized):

    users_sel = param.ListSelector(
        objects=['abc', 'def', 'ghi'])

    @param.output(param.String)
    def user(self):
        return self.users_sel

    @param.depends('users_sel')
    def view(self):
        return pn.widgets.TextInput(value=self.users_sel)

    def panel(self):
        return pn.Row(self.param, self.view)
    
class Stage2(param.Parameterized):

    user = param.String()

    files_sel = param.ObjectSelector()

    @param.output(param.List)
    def file(self):
        return self.users

    @param.depends('user')
    def view(self):
        self.param.files_sel.objects = glob.glob(f'/users/{self.user}/*')
        return pn.widgets.TextInput(value=self.files_sel)

    def panel(self):
        return pn.Row(self.param, self.view)

pipeline = pn.pipeline.Pipeline(
    stages=[('User Input', Stage1), ('Files Input', Stage2)],
    debug=True
)
pipeline

I think you can try to set the disabled value of the button next to True then change it to False when the user click on something.

import glob
import param
import panel as pn

pipeline = pn.pipeline.Pipeline()

class Stage1(param.Parameterized):

    users_sel = param.ListSelector(
        objects=['abc', 'def', 'ghi'])

    @param.output(param.String)
    def user(self):
        if self.users_sel == []:
            return ''
        return self.users_sel[0]

    @param.depends('users_sel')
    def view(self):
        if self.users_sel == []:
            pipeline.header.param.get_param_values()[13][1][2].objects[1].disabled=True
        else:
            pipeline.header.param.get_param_values()[13][1][2].objects[1].disabled=False
        return pn.widgets.TextInput(value=str(self.users_sel))
    

    def panel(self):
        return pn.Row(self.param, self.view)
    
class Stage2(param.Parameterized):

    user = param.String()
    
    @param.depends('user')
    def view(self):
        return pn.widgets.TextInput(value=self.user)

    def panel(self):
        return pn.Row(self.param, self.view)

pipeline = pn.pipeline.Pipeline(
    stages=[('User Input', Stage1), ('Files Input', Stage2)],
    debug=True
)
pipeline.header.param.get_param_values()[13][1][2].objects[1].disabled=True
pn.Column(pipeline.header,pipeline.stage).show()

This example should works but it’s kinda ugly because you need to instantiate an empty pipeline at the beginning. Maybe there is another way to do this with a customjs callback.

The

Programmatic flow control section in the pipelines user guide mentions the ready param, which can do this. https://panel.holoviz.org/user_guide/Pipelines.html

And more in depth information can be found if you look at the actual implementation https://github.com/holoviz/panel/blob/master/panel/pipeline.py