Denjucks render with Deno, undefined is not a function

Viewed 287

I'm using Deno v1.2.1

I cannot for the life of me render a template, I can write to the response easy enough, but rendering is another story, I get undefined is not a function

// Requiring modules 
import { Application, Router, send } from "https://deno.land/x/oak/mod.ts";
import {viewEngine, engineFactory, adapterFactory} from "https://deno.land/x/view_engine/mod.ts";
// Initiate app
const app = new Application();
const router = new Router();
// Setting up boilerplate for view-engine
const renderEngine = await engineFactory.getDenjuckEngine();
const oakAdapter = await adapterFactory.getOakAdapter();

// Adding middleware to require our router
app.use(
  viewEngine(oakAdapter, renderEngine, {
    viewRoot: `${Deno.cwd()}`
  })
);
// Creating Routes
router.get("/",(ctx:any, next)=>{
    ctx.render('index.html') // This gives undefined is not a function
    //ctx.response.body = "hello"; // This works, 
});

app.use(router.routes());
app.use(router.allowedMethods());

// Making app to listen to port
console.log('App is listening to port: 55555');
await app.listen({port:55555});

When I run the code, I get the below, I'm not sure it's related

Warning Failed to get compiled source code of "https://deno.land/std@0.59.0/path/mod.ts".

I'm running the code like this:

deno run --allow-net=0.0.0.0:55555 --allow-read  main.ts

My folder structure is:

_base.html
index.html <- inherits from _base.html
main.ts

Does anyone have any pointers?

5th August 2020 While the below used to work, Deno updates have caused it to stop working, non-inheriting templates and templates that inherit from a base file produce "undefined is not a function"

/_base.html /index.html

<!--_base.html-->
<html>
{% block content %}{% endblock content %}
</html>

<!--index.html-->
{% extends "_base.html" %}

Temp solution 25th July 2020

With help from the comments, I have this code, it works, but the static folders won't work without them being hardcoded into the routes:

// Requiring modules 
import { Application, Router, send } from "https://deno.land/x/oak/mod.ts";
import {viewEngine, engineFactory, adapterFactory} from "https://deno.land/x/view_engine/mod.ts";
// Initiate app
const app = new Application();
const router = new Router();
// Setting up boilerplate for view-engine
const renderEngine = await engineFactory.getDenjuckEngine();
const oakAdapter = await adapterFactory.getOakAdapter();

app.use(viewEngine(oakAdapter, renderEngine));

router
    .get("/", async (context:any, next) => {
       context.render('index.html')

  }).get("/upload", async (context:any, next) => {
    context.cookies.set(
      "lastVisit",
      new Date().toISOString(),
      { httpOnly: true, sameSite: "strict" },
    );

    context.render('upload.html')

  }).get("/images/:file", async (context) => {
     const file = context.params.file;
     await send(context, context.request.url.pathname, {
          root: `${Deno.cwd()}`,
          index: file,
        });
  }).get("/css/:file", async (context) => {
     const file = context.params.file;
     await send(context, context.request.url.pathname, {
          root: `${Deno.cwd()}`,
          index: file,
        });
  }).get("/js/:file", async (context) => {
     const file = context.params.file;
     await send(context, context.request.url.pathname, {
          root: `${Deno.cwd()}`,
          index: file,
        });
  });

app.use(router.routes());
app.use(router.allowedMethods());

app.addEventListener('error', e => {
    console.log(e.error);
});

app.addEventListener('listen', ({hostname, port, secure}) => {
    console.log(`Listening on ${secure ? 'https://' : 'http://'}${hostname || 'localhost'}:${port}`)
});

// Making app to listen to port
await app.listen({port:55555});
1 Answers

Examples Use Oak to render Denjucks template at ./index.html Suppose you have a folder like this:

/index.html
/main.ts

Now in index.html

<!--index.html-->
<body>
  <h1>{{data.name}}</h1>
</body>

Now in main.ts with specific version import,

// main.ts
import { Application } from "https://deno.land/x/oak@v6.0.0/mod.ts";
import {
  viewEngine,
  engineFactory,
  adapterFactory,
} from "https://deno.land/x/view_engine@v1.3.0/mod.ts";

const denjuckEngine = engineFactory.getDenjuckEngine();
const oakAdapter = adapterFactory.getOakAdapter();

const app = new Application();

app.use(viewEngine(oakAdapter, denjuckEngine));

app.use(async (ctx, next) => {
  ctx.render("index.html", { data: { name: "John" } });
});

await app.listen({ port: 8000 });

Then run

deno run --allow-net --allow-read ./main.ts

Open any browser, type http://localhost:8000 you should see the result.

Related