I am new to express-handlebars and finding difficulty in understanding it.
my layout
views
-layouts
-mainlayout.hbs
-partials
-header.hbs(it contains main menu)
-footer.hbs
-patialpage.hbs
pagecontent.hbs
my main page
<div>
{{body}}
</div>
this is my partial page
{{>header}}
<div>
<div>Side Bar Menu</div>
<div>Page Content Here</div>
</div>
{{>footer}}
this is my content
<div>This Content to be append in partial page</div>
You just did in the wrong sequence.
You tried to append the page content to a partial.
In the main layout you define the look of your page.
partials are e.g. parts of this layout (e.g. navbar, footer, ...)
Your main could look like:
<div>
{{> header}}
{{body}}
{{> footer}}
</div>
this means: on each side the header and the footer partial will be loaded and in between, inside {{body}} there will be the rendered view.
example of a main.handlebars file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>title</title>
</head>
<body>
{{!-- navbar partial --}}
{{> _navbar}}
{{!-- flash messages --}}
{{> _flashmessages}}
{{!-- placeholder for rendered views --}}
{{{body}}}
</body>
</html>
then you can render a view based on this main layout.
example with just a text rendered
// Index Route
app.get('/', (req, res) => {
res.send("Hello world");
});
});
example with the view index.handlebars rendered to the {{body}} part of the page
// Index Route
app.get('/', (req, res) => {
res.render('index');
});
I have found a few questions relating to this, but generally there are many different answers and they all seem very messy and complex.
If that is what needs to be done, then ok i better sit down and tackle it.
I want to know what the simplest and most efficient way is to add content to your head from partial views.
Reason I need to do this is i need certain java script and jquery on each page and it differs from page to page. I donot just want to add them all in the _layout view.
You can do this with sections. For example:
I have more than two view which each other has same _Layout.My Index action in Company Controller has a sections as follow:
#model Invoice.Model.HelperClasses.CompanyViewModel
#{
ViewBag.Title = "Companies";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section usage{
<link href="~/css/uniform.default.css" rel="stylesheet" />
}
#section other{
<link href="~/css/datepicker.css" rel="stylesheet" />
<link href="~/css/SimpleSlide.css" rel="stylesheet" />
<link href="~/css/responsive-tables.css" rel="stylesheet" />
}
#section script
{
<script src="~/js/datepicker/bootstrap-datepicker.js"></script>
}
and Display Action in Invoice controller has same sections but different css and js as follow:
#model Invoice.Model.HelperClasses.InvoiceViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section usage{
#*<link href="~/css/uniform.default.css" rel="stylesheet" />*#
}
#section other{
<link href="~/css/DT_bootstrap.css" rel="stylesheet" />
<link href="~/css/responsive-tables.css" rel="stylesheet" />
<script src="~/js/datatables/extras/ZeroClipboard.js"></script>
}
#section script
{
<script src="~/js/datepicker/bootstrap-datepicker.js"></script>
<script src="~/js/validate/jquery.metadata.js"></script>
<script src="~/js/validate/jquery.validate.js"></script>
}
and then you can use this section in _Layout but its required argument should be false. Look at:
<!DOCTYPE html>
<html>
<head>
<!--usage-->
#RenderSection("usage", required: false)
<!--other-->
#RenderSection("other", required: false)
<!--script-->
#RenderSection("script", required: false)
<head>
<body>
</body>
</html>
On your _Layout.cshtml page (Or any other master page) Use following code on inside of <head></head> tag.
#if (IsSectionDefined("SpecialOther"))
{
#RenderSection("SpecialOther")
}
On the page that you want special css,script or any other item, specify their refernces. e.g.,
#section SpecialOther{
<link href="~/css/responsive-tables.css" rel="stylesheet" />
<script src="~/js/datatables/extras/ZeroClipboard.js"></script>
}
Does anyone know if it's possible to hide a layout:fragment if it is not specified in the calling page?
For example, I have a page layout.html that has something like (where there is a separate fragment.html file with header and footer fragments):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
th:lang = "en">
<head>
<title layout:title-pattern="$CONTENT_TITLE">TITLE</title>
</head>
<body>
<header layout:replace="fragment :: header">HEADER</header>
<section layout:fragment="messages">MESSAGES</section>
<section layout:fragment="content">CONTENT</section>
<footer layout:replace="fragment :: footer">FOOTER</footer>
</body>
</html>
If in a calling page to the layout that I don't want to include the "messages" fragment, is there a way to do it by just not including that code? For example (say, simple.html):
<html layout:decorator="layout">
<head>
<title th:text=#{PAGETITLE_SIMPLE}>SIMPLE PAGE TITLE</title>
</head>
<body>
<section layout:fragment="content">
<p>Put in some random content for the body of the simple page</p>
</section>
</body>
This will still put into the rendered HTML the text "MESSAGES" inside a <section>-tag.
I have been able to put into this simple.html
<section layout:fragment="messages" th:remove="all"></section>
But this seems somewhat sloppy and was wondering if there was a way to hide that from the users of the layout by putting the logic in the layout to ignore that fragment altogether.
Using Spring 4.1.6, Thymleaf 2.1.4, and Layout Dialect 1.3.3.
Thanks
I was able to resolve this by applying the methods posted by Serge Ballesta in How to check Thymeleaf fragment is defined to the layout dialect.
This is what the rewritten layout.html looks like:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
th:lang = "en">
<head>
<title layout:title-pattern="$CONTENT_TITLE">TITLE</title>
</head>
<body>
<header layout:replace="fragment :: header">HEADER</header>
<section layout:replace="this :: messages">MESSAGES</section>
<section layout:fragment="content">CONTENT</section>
<footer layout:replace="fragment :: footer">FOOTER</footer>
</body>
</html>
This way, if the calling page (simple.html) only has the <section> for content, no HTML will be rendered for the section for messages. But if the page did have the following, it will be included as intended:
<section layout:fragment="messages">
<p>Message 1</p>
<p>Message 2</p>
</section>
I am trying to embed an R htmlwidget into an existing webpage -- a webpage that already has bootstrap and styling applied. For example, consider the following webpage (note where the widget should be placed):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>This is a test.</p>
<!-- htmlwidget should go here. -->
<p>A closing paragraph.</p>
</body>
</html>
I can create and save a datatable widget like so:
library(htmlwidgets)
library(datatable)
d1 <- datatable(mtcars, filter = "top")
saveWidget(d1, file = "widget_file.html")
The generated widget_file.html (even for this modest widget) contains a lot of code. Is there an easy way to embed this into an existing webpage/template?
I have been successful using <iframe src="widget_file.html"> but I'm wondering if there is a better way? Moreover, is there a way to separate pieces/dependencies (e.g. json data) from the widget_file.html so they can be placed in other folders?
Note: I created the htmlwidget tag, but I believe there should be a synonymous htmlwidgets tag.
The htmlwidget-Package offers a way to save the pieces for the widget separately as follows:
library(dygraphs)
d1 <- dygraph(nhtemp, main = "New Haven Temperatures") %>%
dyRangeSelector(dateWindow = c("1920-01-01", "1960-01-01"))
saveWidget(d1, file = "widget_file.html", selfcontained = FALSE)
Which results in the following files/dirs:
widget_file.html
widget_file_files
/dygraphs-1.1.1
..
/dygraphs-binding-0.6
..
/htmlwidgets-0.5
..
/jquery-1.11.1
..
/moment-2.8.4
..
/moment-timezone-0.2.5
..
And widget_file.html reads as follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="widget_file_files/htmlwidgets-0.5/htmlwidgets.js"></script>
...
<script src="widget_file_files/dygraphs-binding-0.6/dygraphs.js"></script>
</head>
<body style="background-color:white;">
<div id="htmlwidget_container">
<div id="htmlwidget-2956" style="width:960px;height:500px;" class="dygraphs"></div>
</div>
<!-- THE JSON DATA -->
<script type="application/json" data-for="htmlwidget-2956">
{THE JSON DATA YOU WERE LOOKING FOR}
</script>
<!-- THE JSON DATA -->
<script type="application/htmlwidget-sizing" data-for="htmlwidget-2956">{Widget-Styling-Json}
</script>
</body>
</html>
So you can edit your html as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- Begin of scripts to run the widget -->
<script src="widget_file_files/htmlwidgets-0.5/htmlwidgets.js"></script>
<script src="widget_file_files/jquery-1.11.1/jquery.min.js"></script>
<link href="widget_file_files/dygraphs-1.1.1/dygraph.css" rel="stylesheet" />
<script src="widget_file_files/dygraphs-1.1.1/dygraph-combined.js"></script>
<script src="widget_file_files/moment-2.8.4/moment.js"></script>
<script src="widget_file_files/moment-timezone-0.2.5/moment-timezone-with-data.js"></script>
<script src="widget_file_files/dygraphs-binding-0.6/dygraphs.js"></script>
<!-- End of scripts to run the widget -->
<!-- Begin Widget styling -->
<script type="application/htmlwidget-sizing" data-for="htmlwidget-2956">{"viewer":{"width":450,"height":350,"padding":10,"fill":true},"browser":{"width":960,"height":500,"padding":40,"fill":true}}</script>
<!-- End widget Styling -->
<!-- Begin Data for the widget-->
<script type="application/json" data-for="htmlwidget-2956">{"x":{"attrs":{"title":"New Haven Temperatures","labels":["year","V1"],"legend":"auto","retainDateWindow":false,"axes":{"x":{"pixelsPerLabel":60}},"showRangeSelector":true,"dateWindow":["1920-01-01T00:00:00Z","1960-01-01T00:00:00Z"],"rangeSelectorHeight":40,"rangeSelectorPlotFillColor":" #A7B1C4","rangeSelectorPlotStrokeColor":"#808FAB","interactionModel":"Dygraph.Interaction.defaultModel"},"scale":"yearly","annotations":[],"shadings":[],"events":[],"format":"date","data":[["1912-01-01T00:00:00Z","1913-01-01T00:00:00Z","1914-01-01T00:00:00Z","1915-01-01T00:00:00Z","1916-01-01T00:00:00Z","1917-01-01T00:00:00Z","1918-01-01T00:00:00Z","1919-01-01T00:00:00Z","1920-01-01T00:00:00Z","1921-01-01T00:00:00Z","1922-01-01T00:00:00Z","1923-01-01T00:00:00Z","1924-01-01T00:00:00Z","1925-01-01T00:00:00Z","1926-01-01T00:00:00Z","1927-01-01T00:00:00Z","1928-01-01T00:00:00Z","1929-01-01T00:00:00Z","1930-01-01T00:00:00Z","1931-01-01T00:00:00Z","1932-01-01T00:00:00Z","1933-01-01T00:00:00Z","1934-01-01T00:00:00Z","1935-01-01T00:00:00Z","1936-01-01T00:00:00Z","1937-01-01T00:00:00Z","1938-01-01T00:00:00Z","1939-01-01T00:00:00Z","1940-01-01T00:00:00Z","1941-01-01T00:00:00Z","1942-01-01T00:00:00Z","1943-01-01T00:00:00Z","1944-01-01T00:00:00Z","1945-01-01T00:00:00Z","1946-01-01T00:00:00Z","1947-01-01T00:00:00Z","1948-01-01T00:00:00Z","1949-01-01T00:00:00Z","1950-01-01T00:00:00Z","1951-01-01T00:00:00Z","1952-01-01T00:00:00Z","1953-01-01T00:00:00Z","1954-01-01T00:00:00Z","1955-01-01T00:00:00Z","1956-01-01T00:00:00Z","1957-01-01T00:00:00Z","1958-01-01T00:00:00Z","1959-01-01T00:00:00Z","1960-01-01T00:00:00Z","1961-01-01T00:00:00Z","1962-01-01T00:00:00Z","1963-01-01T00:00:00Z","1964-01-01T00:00:00Z","1965-01-01T00:00:00Z","1966-01-01T00:00:00Z","1967-01-01T00:00:00Z","1968-01-01T00:00:00Z","1969-01-01T00:00:00Z","1970-01-01T00:00:00Z","1971-01-01T00:00:00Z"],[49.9,52.3,49.4,51.1,49.4,47.9,49.8,50.9,49.3,51.9,50.8,49.6,49.3,50.6,48.4,50.7,50.9,50.6,51.5,52.8,51.8,51.1,49.8,50.2,50.4,51.6,51.8,50.9,48.8,51.7,51,50.6,51.7,51.5,52.1,51.3,51,54,51.4,52.7,53.1,54.6,52,52,50.9,52.6,50.2,52.6,51.6,51.9,50.5,50.9,51.7,51.4,51.7,50.8,51.9,51.8,51.9,53]]},"evals":["attrs.interactionModel"]}</script>
<!-- End Data for the widget-->
</head>
<body>
<p>This is a test.</p>
<div id="htmlwidget_container">
<div id="htmlwidget-2956" style="width:960px;height:500px;" class="dygraphs"></div>
</div>
<p>A closing paragraph.</p>
</body>
</html>
This will leave you with the json-data hardcoded within the html-document (see my ).
If you want to load the data dynamically you can use e.g.
json_dat <- readLines("widget_file.html")[18]
cat(sub("</script>","",sub('<script type=\"application/json\" data-for=.*\">', "", json_dat)), file = "./widget_file_files/my_data.json")
To save the json-data as ./widget_file_files/my_data.json and then load it within the html. If you are using PHP you can do:
<script type="application/json" data-for="htmlwidget-2956">
<?php include('widget_file_files/my_data.json'); ?>
</script>
If you want to use a pure JS solution maybe have a look at http://api.jquery.com/jquery.getjson/ and the widget_file_files/htmlwidgets-0.5/htmlwidgets.js-File how the json-data is bound at the moment...
P.S.:
As this question got a lot of attention already you could also contact the package developer and ask him to further "un-selfcontain" the "selfcontained" option in htmlwidgets:::saveWidget: Meaning to save the json-data separately and include it e.g. via jquery.getjson