Repository: holoviz/panel

Issue:
param.Action buttons do not respond to parameter attribute changes
As an example the label is not updated when it changes.


Discussion:

Resolving patch:
diff --git a/panel/param.py b/panel/param.py
--- a/panel/param.py
+++ b/panel/param.py
@@ -323,11 +323,7 @@ def widget(self, p_name):
             widget = widget_class(**kwargs)
 
         watchers = self._callbacks
-        if isinstance(p_obj, param.Action):
-            def action(change):
-                value(self.object)
-            watchers.append(widget.param.watch(action, 'clicks'))
-        elif isinstance(widget, Toggle):
+        if isinstance(widget, Toggle):
             pass
         else:
             def link_widget(change):
@@ -339,8 +335,14 @@ def link_widget(change):
                 finally:
                     self._updating = False
 
-            widget.param.watch(link_widget, 'value')
-            def link(change):
+            if isinstance(p_obj, param.Action):
+                def action(change):
+                    value(self.object)
+                watcher = widget.param.watch(action, 'clicks')
+            else:
+                watcher = widget.param.watch(link_widget, 'value')
+
+            def link(change, watchers=[watcher]):
                 updates = {}
                 if change.what == 'constant':
                     updates['disabled'] = change.new
@@ -367,8 +369,16 @@ def link(change):
                     updates['end'] = end
                 elif change.what == 'step':
                     updates['step'] = p_obj.step
+                elif change.what == 'label':
+                    updates['name'] = p_obj.label
                 elif self._updating:
                     return
+                elif isinstance(p_obj, param.Action):
+                    widget.param.unwatch(watchers[0])
+                    def action(event):
+                        change.new(self.object)
+                    watchers[0] = widget.param.watch(action, 'clicks')
+                    return
                 else:
                     updates['value'] = change.new
 
@@ -381,6 +391,7 @@ def link(change):
             # Set up links to parameterized object
             watchers.append(self.object.param.watch(link, p_name, 'constant'))
             watchers.append(self.object.param.watch(link, p_name, 'precedence'))
+            watchers.append(self.object.param.watch(link, p_name, 'label'))
             if hasattr(p_obj, 'get_range'):
                 watchers.append(self.object.param.watch(link, p_name, 'objects'))
             if hasattr(p_obj, 'get_soft_bounds'):


Test patch:
diff --git a/panel/tests/test_param.py b/panel/tests/test_param.py
--- a/panel/tests/test_param.py
+++ b/panel/tests/test_param.py
@@ -397,6 +397,24 @@ class Test(param.Parameterized):
     assert test_pane._widgets['a'] in test_pane._widget_box.objects
 
 
+def test_param_label(document, comm):
+    class Test(param.Parameterized):
+        a = param.Number(default=1.2, bounds=(0, 5), label='A')
+        b = param.Action(label='B')
+
+    test = Test()
+    test_pane = Pane(test)
+
+    # Check updating label changes widget name
+    a_param = test.param['a']
+    a_param.label = 'B'
+    assert test_pane._widgets['a'].name == 'B'
+
+    b_param = test.param['b']
+    b_param.label = 'C'
+    assert test_pane._widgets['b'].name == 'C'
+
+
 def test_param_precedence_ordering(document, comm):
     class Test(param.Parameterized):
         a = param.Number(default=1.2, bounds=(0, 5), precedence=-1)