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.