Repository: holoviz/panel

Issue:
Update Viewer  to work with depends on `__panel__`

#### Is your feature request related to a problem? Please describe.
I often have some code that looks like this:
``` python
import panel as pn
import param


class Example(pn.viewable.Viewer):
    def __init__(self, **params):
        self.button = pn.widgets.Button(name="Click")
        super().__init__(**params)

    @param.depends("button.clicks")
    def __panel__(self):
        return pn.Column(self.button, self.button.clicks)


ex = Example()
ex.servable() 
``` 

![1](https://user-images.githubusercontent.com/19758978/150692802-39cd9746-83fe-472b-8c15-95610a1a4a12.gif)

Which does not update when pressing the button, what I need to do is change the last line to `pn.panel(ex.__panel__).servable()` or add an extra function like this to get it to work.
``` python
class Example(pn.viewable.Viewer):
    def __init__(self, **params):
        self.button = pn.widgets.Button(name="Click")
        super().__init__(**params)

    @param.depends("button.clicks")
    def _return_click(self):
        return self.button.clicks
    
    def __panel__(self):
        return pn.Column(self.button, self._return_click)
```

![2](https://user-images.githubusercontent.com/19758978/150692806-9ecc4b91-6078-4839-bf9c-c571704e7e0e.gif)


#### Describe the solution you'd like
The solution to this particular problem seems to update the `Viewer` to something like the following. But if there is a reason why this was not done in the first place, I would like to hear it as it seems pretty fundamental to my understanding of param/panel.

![viewer](https://user-images.githubusercontent.com/19758978/150692844-80c7e677-d1f2-42e4-af64-411485dc9d6c.png)



Discussion:
I've been experiencing and thinking the same.
I'd be okay with this change but at minimum I'd only perform the wrapping into a `ParamMethod` or `ParamFunction` object (i.e. what you're doing by wrapping `pn.panel(self.__panel__)`) if actually needed, otherwise this will add pointless nesting and overhead for no reason.
Seem like the natural thing to do. 

Do you have a link to `ParamMethod` or `ParamFunction`? I would like to know exactly what they do and what the difference is between them.
The difference is just that one's for standalone functions and one's for object methods:

https://panel.holoviz.org/api/panel.param.html#panel.param.ParamFunction
https://panel.holoviz.org/api/panel.param.html#panel.param.ParamMethod



Resolving patch:
diff --git a/panel/viewable.py b/panel/viewable.py
--- a/panel/viewable.py
+++ b/panel/viewable.py
@@ -819,14 +819,24 @@ def __panel__(self):
         """
         raise NotImplementedError
 
+    def _create_view(self):
+        from .param import ParamMethod
+
+        if hasattr(self.__panel__, "_dinfo"):
+            view = ParamMethod(self.__panel__)
+        else:
+            view = self.__panel__()
+
+        return view
+
     def servable(self, title=None, location=True):
-        return self.__panel__().servable(title, location)
+        return self._create_view().servable(title, location)
 
     servable.__doc__ = ServableMixin.servable.__doc__
 
     def show(self, title=None, port=0, address=None, websocket_origin=None,
              threaded=False, verbose=True, open=True, location=True, **kwargs):
-        return self.__panel__().show(
+        return self._create_view().show(
             title, port, address, websocket_origin, threaded,
             verbose, open, location, **kwargs
         )
@@ -834,4 +844,4 @@ def show(self, title=None, port=0, address=None, websocket_origin=None,
     show.__doc__ = ServableMixin.show.__doc__
 
     def _repr_mimebundle_(self, include=None, exclude=None):
-        return self.__panel__()._repr_mimebundle_(include, exclude)
+        return self._create_view()._repr_mimebundle_(include, exclude)


Test patch: