Commit b7608adc authored by Paul's avatar Paul

Simple Bootstrap Example

parent 650ab880
# Bootstrap Templates Example
This example is to show how to invert the dependencies in Simple
Template to create extensible templates from a base. It has been
created using [Bootstrap](https://getbootstrap.com/) version 4.
## The Bootstrap Base Template
We begin with a very generic base template for bootstrap, you can read
it in `templates/bootstrap_base.html`. You'll find lots and lots of
`{{ if some_var }}{{ dynamic_include some_var }}{{end}}` type
statements in there. For this reason the `config.pl` file sets
`st_undefined` to false, so these variables don't have to be set. This
creates an extensible base that we can use to create our
application.
## Easy Similar Templates
Often we want very similar templates with only a few small
differences, for example we'll want the same navigation, or same styles
or scripts on a bunch of related pages. The example shows one way to
achieve this in the `home_template/2` predicate in `main.pl`. This
accepts a `CustomDict` of unique content and joins it to
`Home`, which is shared content. Using this method you can create
different but similar templates for all your related routes.
## Gotchas
In this example, blocks clobber each other. Take a look at
`templates/bootstrap_base.html` and `templates/styles_eg.html`, you'll
see that the link to `bootstrap.min.css` had to be included in
`templates/styles_eg.html` because the inclusion of `styles`
overwrote the automatic inclusion of it. This is a deliberate design
choice to allow maximum flexibility and it could be expanded even
further to the whole head, body and html tags.
## Subtle `favicon.ico` trick
In `templates/bootstrap_base.html` you'll see a `<link>` tag that
defines the source of the `favicon.ico` to be in `static/images`. This
removes the headache of having to declare a route just for that.
# Bootstrap Templates Example
This example is to show how to invert the dependencies in Simple
Template to create extensible templates from a base. It has been
created using [Bootstrap](https://getbootstrap.com/) version 4.
## The Bootstrap Base Template
We begin with a very generic base template for bootstrap, you can read
it in `templates/bootstrap_base.html`. You'll find lots and lots of
`{{ if some_var }}{{ dynamic_include some_var }}{{end}}` type
statements in there. For this reason the `config.pl` file sets
`st_undefined` to false, so these variables don't have to be set. This
creates an extensible base that we can use to create our
application.
## Easy Similar Templates
Often we want very similar templates with only a few small
differences, for example we'll want the same navigation, or same styles
or scripts on a bunch of related pages. The example shows one way to
achieve this in the `home_template/2` predicate in `main.pl`. This
accepts a `CustomDict` of unique content and joins it to
`Home`, which is shared content. Using this method you can create
different but similar templates for all your related routes.
## Gotchas
In this example, blocks clobber each other. Take a look at
`templates/bootstrap_base.html` and `templates/styles_eg.html`, you'll
see that the link to `bootstrap.min.css` had to be included in
`templates/styles_eg.html` because the inclusion of `styles`
overwrote the automatic inclusion of it. This is a deliberate design
choice to allow maximum flexibility and it could be expanded even
further to the whole head, body and html tags.
## Subtle `favicon.ico` trick
In `templates/bootstrap_base.html` you'll see a `<link>` tag that
defines the source of the `favicon.ico` to be in `static/images`. This
removes the headache of having to declare a route just for that.
# Bootstrap Templates Example
This example uses `library(sw/simple_bootstrap)`, minimum version 0.0.2,
which can be installed with:
```
?- pack_install(simple_bootstrap).
```
## As Per DIY
This is not dissimilar from the [DIY Version](../diy), except you'll
notice there's a lot less in the directory structure as much is provided
for you in Simple Bootstrap. This is the "quick start" version.
## Easy Similar Templates
Often we want very similar templates with only a few small
differences, for example we'll want the same navigation, or same styles
or scripts on a bunch of related pages. The example shows one way to
achieve this in the `home_template/2` predicate in `main.pl`. This
accepts a `CustomDict` of unique content and joins it to
`Home`, which is shared content. Using this method you can create
different but similar templates for all your related routes.
## Gotchas Resolved
Using Simple Bootstrap, you can overcome the clobbering issue of
overwriting blocks by re-including them in your templates. For example,
with styles:
```html
{{ dynamic_include bootstrap("styles") }}
<link href="/static/css/my_styles.css" rel="stylesheet">
```
:- module(main,
[ serve/0
]
).
% Assert app dir so it can be run from anywhere
:- prolog_load_context(directory, Dir),
asserta(user:file_search_path(sw_app, Dir)).
:- use_module(library(sw/simple_web)).
:- use_module(library(sw/simple_bootstrap)).
%! join_dicts(+D1, +D2, -D3) is nondet.
% Join dicts together if there is no
% conflict
join_dicts(D1, D2, D3) :-
D1 >:< D2,
put_dict(D1, D2, D3).
%! home_template(+CustomDict, -Template) is nondet.
% Merge custom options into the common home template
% options.
home_template(CustomDict, Template) :-
Home = _{ navbar: navbar_eg
, styles: styles_eg
},
join_dicts(CustomDict, Home, Template).
sw:route('/', _Request) :-
home_template(template{ title: 'Hello Bootstrap'
, content: content_eg
, content_message: "You can include data for templates too!"
}, Template),
reply_template(bootstrap_base, Template).
serve :-
run(port(8000)).
body {
padding-top: 5rem;
}
.starter-template {
padding: 3rem 1.5rem;
text-align: center;
}
<div class="starter-template">
<h1>Bootstrap starter template</h1>
<p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
<p><strong>{{= content_message }}</strong></p>
</div>
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Disabled</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="https://example.com" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
<div class="dropdown-menu" aria-labelledby="dropdown01">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
{{ dynamic_include bootstrap("styles") }}
<link href="/static/css/main_styles.css" rel="stylesheet">
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment