Repository: iterative/dvc

Issue:
plots: custom templates not being read from `.dvc/plots`
## Description

Custom templates saved in `.dvc/plots` are not being read in `dvc plots` commands. It looks like this was introduced in #7409.

### Reproduce

```console
$ git clone https://github.com/iterative/example-get-started.git
Cloning into 'example-get-started'...
remote: Enumerating objects: 113, done.
remote: Counting objects: 100% (105/105), done.
remote: Compressing objects: 100% (73/73), done.
remote: Total 113 (delta 34), reused 90 (delta 29), pack-reused 8
Receiving objects: 100% (113/113), 150.41 KiB | 4.06 MiB/s, done.
Resolving deltas: 100% (34/34), done.
$ cd example-get-started
$ dvc plots templates linear
Templates have been written into '.dvc/plots'.
$ mv .dvc/plots/linear.json .dvc/plots/custom.json
$ dvc plots show -v -t custom
2022-05-26 17:07:11,405 ERROR: unexpected error - Template 'custom' not found.
------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dave/Code/dvc/dvc/cli/__init__.py", line 78, in main
    ret = cmd.do_run()
  File "/Users/dave/Code/dvc/dvc/cli/command.py", line 22, in do_run
    return self.run()
  File "/Users/dave/Code/dvc/dvc/commands/plots.py", line 74, in run
    renderers = match_renderers(
  File "/Users/dave/Code/dvc/dvc/render/match.py", line 52, in match_renderers
    renderer_class(datapoints, filename, **plot_properties)
  File "/Users/dave/miniforge3/envs/example-get-started/lib/python3.8/site-packages/dvc_render/vega.py", line 37, in __init__
    self.template = get_template(
  File "/Users/dave/miniforge3/envs/example-get-started/lib/python3.8/site-packages/dvc_render/vega_templates.py", line 562, in get_template
    raise TemplateNotFoundError(template)
dvc_render.vega_templates.TemplateNotFoundError: Template 'custom' not found.
------------------------------------------------------------
2022-05-26 17:07:11,776 DEBUG: Version info for developers:
DVC version: 2.9.6.dev49+gddd6c97f7
---------------------------------
Platform: Python 3.8.5 on macOS-10.16-x86_64-i386-64bit
Supports:
        azure (adlfs = 2022.2.0, knack = 0.7.2, azure-identity = 1.5.0),
        gdrive (pydrive2 = 1.10.1),
        gs (gcsfs = 2022.2.0),
        hdfs (fsspec = 2022.2.0, pyarrow = 3.0.0),
        webhdfs (fsspec = 2022.2.0),
        http (aiohttp = 3.7.3, aiohttp-retry = 2.4.6),
        https (aiohttp = 3.7.3, aiohttp-retry = 2.4.6),
        s3 (s3fs = 2022.2.0, boto3 = 1.20.24),
        ssh (sshfs = 2021.11.2),
        oss (ossfs = 2021.8.0),
        webdav (webdav4 = 0.9.4),
        webdavs (webdav4 = 0.9.4)
Cache types: <https://error.dvc.org/no-dvc-cache>
Caches: local
Remotes: https
Workspace directory: apfs on /dev/disk3s1s1
Repo: dvc, git

Having any troubles? Hit us up at https://dvc.org/support, we are always happy to help!
2022-05-26 17:07:11,778 DEBUG: Analytics is disabled.
```



Discussion:

Resolving patch:
diff --git a/dvc/commands/plots.py b/dvc/commands/plots.py
--- a/dvc/commands/plots.py
+++ b/dvc/commands/plots.py
@@ -75,7 +75,9 @@ def run(self):
                 out if self.args.json else os.path.join(out, "static")
             )
             renderers = match_renderers(
-                plots_data=plots_data, out=renderers_out
+                plots_data=plots_data,
+                out=renderers_out,
+                templates_dir=self.repo.plots.templates_dir,
             )
 
             if self.args.show_vega:
diff --git a/dvc/render/match.py b/dvc/render/match.py
--- a/dvc/render/match.py
+++ b/dvc/render/match.py
@@ -49,7 +49,7 @@ def match_renderers(
                 if out is not None:
                     plot_properties["out"] = out
                 if templates_dir is not None:
-                    plot_properties["templates_dir"] = templates_dir
+                    plot_properties["template_dir"] = templates_dir
                 datapoints, plot_properties = to_datapoints(
                     renderer_class, group, plot_properties
                 )
diff --git a/dvc/repo/plots/__init__.py b/dvc/repo/plots/__init__.py
--- a/dvc/repo/plots/__init__.py
+++ b/dvc/repo/plots/__init__.py
@@ -228,7 +228,8 @@ def modify(self, path, props=None, unset=None):
 
     @cached_property
     def templates_dir(self):
-        return os.path.join(self.repo.dvc_dir, "plots")
+        if self.repo.dvc_dir:
+            return os.path.join(self.repo.dvc_dir, "plots")
 
 
 def _is_plot(out: "Output") -> bool:


Test patch:
diff --git a/tests/unit/command/test_plots.py b/tests/unit/command/test_plots.py
--- a/tests/unit/command/test_plots.py
+++ b/tests/unit/command/test_plots.py
@@ -240,6 +240,36 @@ def test_plots_path_is_quoted_and_resolved_properly(
     assert expected_url in out
 
 
+def test_should_pass_template_dir(tmp_dir, dvc, mocker, capsys):
+    cli_args = parse_args(
+        [
+            "plots",
+            "diff",
+            "HEAD~1",
+            "--json",
+            "--targets",
+            "plot.csv",
+        ]
+    )
+    cmd = cli_args.func(cli_args)
+
+    data = mocker.MagicMock()
+    mocker.patch("dvc.repo.plots.diff.diff", return_value=data)
+
+    renderers = mocker.MagicMock()
+    match_renderers = mocker.patch(
+        "dvc.render.match.match_renderers", return_value=renderers
+    )
+
+    assert cmd.run() == 0
+
+    match_renderers.assert_called_once_with(
+        plots_data=data,
+        out="dvc_plots",
+        templates_dir=str(tmp_dir / ".dvc/plots"),
+    )
+
+
 @pytest.mark.parametrize(
     "output", ("some_out", os.path.join("to", "subdir"), None)
 )
diff --git a/tests/unit/render/test_match.py b/tests/unit/render/test_match.py
--- a/tests/unit/render/test_match.py
+++ b/tests/unit/render/test_match.py
@@ -178,3 +178,18 @@ def test_match_renderers_with_out(tmp_dir, mocker):
     assert (
         tmp_dir / "foo" / "workspace_other_file.jpg"
     ).read_bytes() == b"content2"
+
+
+def test_match_renderers_template_dir(mocker):
+    from dvc_render import vega
+
+    vega_render = mocker.spy(vega.VegaRenderer, "__init__")
+    data = {
+        "v1": {
+            "data": {"file.json": {"data": [{"y": 4}, {"y": 5}], "props": {}}}
+        },
+    }
+
+    match_renderers(data, templates_dir="foo")
+
+    assert vega_render.call_args[1]["template_dir"] == "foo"