dart_frog icon indicating copy to clipboard operation
dart_frog copied to clipboard

feat: HTML template support

Open paurakhsharma opened this issue 2 years ago • 12 comments

Description As a user, I want to be able to respond with an HTML template.

If we don't want to implement it in this core project. Would love to see separate project to support it as a plugin either by VG team themselves or by the community.

paurakhsharma avatar Jun 14 '22 03:06 paurakhsharma

Hi @paurakhsharma 👋 Thanks for opening an issue!

Can you please provide a bit more context regarding the expectation? Currently, you can create an endpoint that responds with html like:

import 'dart:io';

import 'package:dart_frog/dart_frog.dart';

Response onRequest(RequestContext context) {
  return Response(
    body: '<p>Hello World</p>',
    headers: {HttpHeaders.contentTypeHeader: ContentType.html.value},
  );
}

felangel avatar Jun 14 '22 05:06 felangel

That is awesome. I can see we can use String interpolation for adding some values from the variable. But other things like looping or conditional rendering might be difficult.

I was thinking something like.

import 'dart:io';

import 'package:dart_frog/dart_frog.dart';

Response onRequest(RequestContext context) {
  return RenderTemplate(
            'index.html',
             params: {
                 "hello": "world",
                 "bestLanguages": ["Dart", "Dart"],
                 "isDartFrogAwesome": true,
              }
        );
}

And in templates/index.html

<p>Hello {{hello}}</p>

<div>
   {% for language in bestLanguages %}
        <li>{{ language|toUpperCase }}</li>
    {% endfor %}
</div>

{% if isDartFrogAwesome %}
    <p>Dart Frog is awesome 🚀</p>
{% endif %}

paurakhsharma avatar Jun 14 '22 05:06 paurakhsharma

@paurakhsharma thanks for clarifying! I definitely think this can be supported via a separate package. I’ll discuss with the team and update the ROADMAP accordingly, thanks again 🙏

felangel avatar Jun 14 '22 05:06 felangel

Amazing! Thank you so much 😊

paurakhsharma avatar Jun 14 '22 05:06 paurakhsharma

What do you think of OverReact to assemble the html?

render() {
  return (Dom.div()..className = 'container')(
    Dom.h1()('Click the button!'),
    (Dom.button()
      ..id = 'main_button'
      ..onClick = _handleClick
    )('Click me')
  );
}

AlvaroVasconcelos avatar Jun 24 '22 00:06 AlvaroVasconcelos

Hi, @felangel is it possible to return an HTML file directly in the response?

Mastersam07 avatar Aug 20 '22 09:08 Mastersam07

@Mastersam07 Yes, you can.

// routes/index.dart

import 'dart:io';

import 'package:dart_frog/dart_frog.dart';
import 'package:path/path.dart' as path;

Response onRequest(RequestContext context) {
  final file = File(path.join(Directory.current.path, 'public', 'index.html'));
  if (!file.existsSync()) {
    return Response(body: 'Index Not found');
  }
  final indexHtml = file.readAsStringSync();
  return Response(body: indexHtml, headers: {'Content-Type': 'text/html'});
}

ushieru avatar Sep 13 '22 02:09 ushieru

If you just want to respond with a static html file you can just serve the static asset

felangel avatar Sep 13 '22 02:09 felangel

Thanks, @ushieru @felangel. I already found a solution to the issue.

Mastersam07 avatar Sep 13 '22 07:09 Mastersam07

What do you guys think of jasper?

AlvaroVasconcelos avatar Feb 07 '23 15:02 AlvaroVasconcelos

Hello @paurakhsharma @felangel

I recently wrote an article that illustrates how to use HTML templates in a dart frog application using the jinja package. https://yande.hashnode.dev/jinja-html-templates-with-dart-frog

A Quick Explanation:

pubspec.yaml

dependencies:
    ...
    jinja: ^0.5.0

routes/index.dart

import 'package:dart_frog/dart_frog.dart';
import 'package:jinja/jinja.dart';
import 'package:jinja/loaders.dart';

Response onRequest(RequestContext context) {
  final environment = Environment(
    loader: FileSystemLoader(
      paths: [
        'templates'
      ],
    ),
  );

  final template = environment.getTemplate(
    'base.html',
  );

  final tutorials = [
    'Jinja Templates Tutorial',
    'Flutter Tutorials',
    'Dart Fundamentals',
  ];

  return Response(
    body: template.render({
      'title': 'Home',
      'tutorials': tutorials,
    }),
    headers: {
      'Content-Type': 'text/html'
    },
  );
}

templates/base.html

<html lang="en">

<head>

  <meta charset="utf-8">

  <title>{{ title }}</title>

</head>

<body>

  <h1>Welcome to {{ title }}!</h1>

  {% for tutorial in tutorials %}

  <ul>

    <li>

      {{ tutorial }}</em>

    </li>

  </ul>

  {% endfor %}

</body>

</html>

Output

Screenshot 2023-08-22 at 17 21 39

I hope this helps.

Eghosa-Osayande avatar Aug 22 '23 17:08 Eghosa-Osayande

Nice read @Eghosa-Osayande

I also resorted to using jinja templating given that i have background in django and used jinja template in the past. I forgot to mention in my last update on this issue.

Mastersam07 avatar Aug 22 '23 17:08 Mastersam07