Repository: gradio-app/gradio

Issue:
Pagination for Examples
As a gradio user, I would like to provide many examples for my app without displaying all of them in the page when the app loads.

As a possible solution, we should expose an `overflow_row_behavior` for `Dataset`/`Examples` like we do for `Dataframe`.

This was originally asked in the Discussion sections:

> Most of the demo that use gr.Examples add sample statically. Is it currently possible to load/update samples dynamically in the case one have a large dataset so potentially need pagination ?
> 
> _Originally posted by @jrabary in https://github.com/gradio-app/gradio/discussions/2163_


Discussion:
Would it be possible to somehow achieve this using Blocks in the meantime? I'd like to implement a pagination feature but can't seem to figure out how to.

EDIT: I just saw your example in the linked discussion and tabs are what I was after! Sorry for the noise.
Awesome @cakiki !

Also FYI - if you have more than 10 examples gradio will paginate them for you as well

```python
import gradio as gr

with gr.Blocks() as demo:
    current_example_values = gr.State([])
    input_ = gr.Number(label="Input")
    output = gr.Number(label="Input * 2")
    calc = gr.Button(value="Calculate")
    examples = gr.Examples(examples=[[i] for i in range(20)], inputs=[input_])
    calc.click(lambda s: s * 2, input_, output)

demo.launch()
```

<img width="1317" alt="image" src="https://user-images.githubusercontent.com/41651716/207631487-83f11c65-dc4f-4e65-981e-801019ad2d8f.png">

There is an `examples_per_page` argument that lets you control how many examples are needed before pagination happens. But it's not being passed all the way through. Will fix that soon!


Resolving patch:
diff --git a/gradio/components.py b/gradio/components.py
--- a/gradio/components.py
+++ b/gradio/components.py
@@ -4834,6 +4834,7 @@ def __init__(
         samples: List[List[Any]] = None,
         headers: Optional[List[str]] = None,
         type: str = "values",
+        samples_per_page: int = 10,
         visible: bool = True,
         elem_id: Optional[str] = None,
         **kwargs,
@@ -4844,6 +4845,7 @@ def __init__(
             samples: a nested list of samples. Each sublist within the outer list represents a data sample, and each element within the sublist represents an value for each component
             headers: Column headers in the Dataset widget, should be the same len as components. If not provided, inferred from component labels
             type: 'values' if clicking on a sample should pass the value of the sample, or "index" if it should pass the index of the sample
+            samples_per_page: how many examples to show per page.
             visible: If False, component will be hidden.
             elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles.
         """
@@ -4861,6 +4863,7 @@ def __init__(
             self.headers = []
         else:
             self.headers = [c.label or "" for c in self.components]
+        self.samples_per_page = samples_per_page
 
     def get_config(self):
         return {
@@ -4869,6 +4872,7 @@ def get_config(self):
             "samples": self.samples,
             "type": self.type,
             "label": self.label,
+            "samples_per_page": self.samples_per_page,
             **Component.get_config(self),
         }
 
diff --git a/gradio/examples.py b/gradio/examples.py
--- a/gradio/examples.py
+++ b/gradio/examples.py
@@ -97,7 +97,7 @@ def __init__(
             outputs: optionally, provide the component or list of components corresponding to the output of the examples. Required if `cache` is True.
             fn: optionally, provide the function to run to generate the outputs corresponding to the examples. Required if `cache` is True.
             cache_examples: if True, caches examples for fast runtime. If True, then `fn` and `outputs` need to be provided
-            examples_per_page: how many examples to show per page (this parameter currently has no effect)
+            examples_per_page: how many examples to show per page.
             label: the label to use for the examples component (by default, "Examples")
             elem_id: an optional string that is assigned as the id of this component in the HTML DOM.
             run_on_click: if cache_examples is False, clicking on an example does not run the function when an example is clicked. Set this to True to run the function when an example is clicked. Has no effect if cache_examples is True.
@@ -182,7 +182,6 @@ def __init__(
         self.outputs = outputs
         self.fn = fn
         self.cache_examples = cache_examples
-        self.examples_per_page = examples_per_page
         self._api_mode = _api_mode
         self.preprocess = preprocess
         self.postprocess = postprocess
@@ -218,6 +217,7 @@ def __init__(
                 samples=non_none_examples,
                 type="index",
                 label=label,
+                samples_per_page=examples_per_page,
                 elem_id=elem_id,
             )
 


Test patch:
diff --git a/test/test_examples.py b/test/test_examples.py
--- a/test/test_examples.py
+++ b/test/test_examples.py
@@ -45,6 +45,10 @@ def test_handle_directory_with_log_file(self):
         for sample in examples.dataset.samples:
             assert os.path.isabs(sample[0])
 
+    def test_examples_per_page(self):
+        examples = gr.Examples(["hello", "hi"], gr.Textbox(), examples_per_page=2)
+        assert examples.dataset.get_config()["samples_per_page"] == 2
+
     @pytest.mark.asyncio
     async def test_no_preprocessing(self):
         with gr.Blocks():
diff --git a/test/test_interfaces.py b/test/test_interfaces.py
--- a/test/test_interfaces.py
+++ b/test/test_interfaces.py
@@ -132,10 +132,13 @@ def test_interface_browser(self, mock_browser):
 
     def test_examples_list(self):
         examples = ["test1", "test2"]
-        interface = Interface(lambda x: x, "textbox", "label", examples=examples)
+        interface = Interface(
+            lambda x: x, "textbox", "label", examples=examples, examples_per_page=2
+        )
         interface.launch(prevent_thread_lock=True)
         assert len(interface.examples_handler.examples) == 2
         assert len(interface.examples_handler.examples[0]) == 1
+        assert interface.examples_handler.dataset.get_config()["samples_per_page"] == 2
         interface.close()
 
     @mock.patch("IPython.display.display")