I was trying to get a struct passed to a nested template in Go, using html/template and tried to achieve it using both template.ParseFiles and template.ParseGlob, but it is not working as per my expectation because my understanding is not clear.
My template code for the file header.html is
{{define "header"}}
<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title> SiteAdmin - {{.User}}</title>
</head>
{{end}}
and for the file admin.html is
{{template "header"}}
<body>
"User is {{.User}}"
</body>
</html>
I am using the Execute method on the type *Template as
type Admin struct {
User string
}
data := new(Admin)
data.User = "Guest"
tpl, err := template.ParseGlob("views/templates/admin/*.html")
CheckForErr(err)
err = tpl.Execute(w, data)
CheckForErr(err)
With the above code, I can pass around the struct data to admin.html, and it shows User is Guest in the browser. But if I try to pass it to any of the nested templates, it wouldn't. The title of the page still shows as SiteAdmin - and not SiteAdmin - Guest. The User data from the struct is visible only if I call it as {{.User}} inside the admin.html file, and any reference to it in the nested templates turns out to be not passed. Is this something achievable?
Thank you all.
You need to use {{ template "header" . }}. As the document in text/template say:
{{template "name" pipeline}}
The template with the specified name is executed with dot set
to the value of the pipeline.
In this case, the pipeline you passed into is ., which reffers to the whole data.
It is somehow unconvenient that documents of html/template is mostly in text/template.
Related
I'm totally new in Thymeleaf. Just read about it earlier, now, I'm trying to display some text using Thymeleaf in the front end, getting the values from Spring MVC in back-end.
File successPwd.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta charset="UTF-8"/>
<title>Password Change</title>
</head>
<body>
<h2>Password Changed</h2>
Your password has been changed. Your account information is below.
Username: [[${account.username}]] <br/>
First Name: [[${account.firstName}]] <br/>
Last Name: [[${account.surname}]] <br/>
</body>
</html>
File PasswordResetController.java
#RequestMapping(value= "/user/new_password", method = RequestMethod.POST)
public String saveNewPassword(#RequestParam(value="new_password",required=false) String password, #RequestParam(value="hash") String hash, Model model)
{
//some codes to check hash
AccountInfo account = accountInfoService.getAccount(hash);
model.addAttribute("account", account);
return "/successPwd";
}
What I'm getting is like this:
Password Changed
Your password has been changed. Your account information is below.
Username: [[${account.username}]]
First Name: [[${account.firstName}]]
Last Name: [[${account.surname}]]
Thymeleaf is not converting to the proper values, most likely I missed something very very basic here.
In this case, you should use th:text. For example, Username: <p th:text=${account.username}>Username will be rendered here</p>. Note that, the text inside p tag won't be shown.
See here for more details: Standard thymeleaf syntax
If you want to get rid of the "awkward" Html tag you can do as follows.
<span th:text="${account.username}" th:remove="tag">userName</span>
How to add title and favicon in meteor 1.3, using iron router and blaze ?
In js you can set the page title anytime with:
document.title = "Foo";
This is much more flexible than including a static title in the <head> section as you generally want the title to change on a route-by-route basis.
In i-r you can do this in an onAfterAction hook ex:
onAfterAction() {
document.title = 'mySiteName:' + Router.current().route.getName();
}
The icon can also be set dynamically, see this question
In the default layout template of iron router add the following lines in the starting of the html file.
<head>
<link rel='icon' sizes="16x16 32x32" href='/favicon.ico' >
</head>
Save the /favicon.ico in public directory in the meteor root app. Don't forget the / in /favicon.ico
For favicon, add the following code in your main.html page in the head tag
<link rel='shortcut icon' type='image/x-icon' href='favicon.ico' />
For title per page, you can add in each html template the following code
{{documentTitle 'Document Title'}}
And add the following code in a js file
//global template helper
Template.registerHelper('documentTitle', function(title){
document.title = title;
});
You can use head tag inside the client/main.html file.
This will allow you to add title and favicon icon.
<head>
<meta charset="utf-8" />
<title>MY Title</title>
<link rel='shortcut icon' href='favicon.ico' type='image/x-icon'/ >
</head>
I have two html files that are parsed as follows:
var LoginTemplate = template.Must(template.ParseFiles(
"views/_base.html",
"views/login.html",
))
And executed as such:
func LoginFormHandler(w http.ResponseWriter, r *http.Request, ctx *models.Context) error {
err := LoginTemplate.Execute(w, ctx)
if err != nil {
http.Error(w, err.Error(), 404)
}
return nil
}
Here are the contents of _base.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- Meta, title, CSS, favicons, etc. -->
<meta charset="utf-8">
<title>{{ template "title" . }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{ template "styles" . }}
{{ template "scripts" . }}
</head>
{{ template "content" . }}
</html>
The templates specified above are all defined in login.html. For example, "styles" wraps all of my CSS links, etc. In my main function, I use a gorilla/pat router to handle several page requests to the server. Additionally, I want to serve my static assets folders like this:
router.PathPrefix("/assets/").Handler(http.StripPrefix("/assets/", http.FileServer(http.Dir("./assets/"))))
if err := http.ListenAndServe(":"+settings.Server.Port, router); err != nil {
panic(err)
}
However, upon building and running my program, then navigating to local host, I see that none of the CSS or js appears to be rendering. My css and js folders are in this tree:
ROOT/
assets/
css/
js/
I am downloading part of an HTML page by:
require 'nokogiri'
require 'open-uri'
doc = Nokogiri::HTML(open('https://example.com/index.html'))
wiki = doc./('//*[#id="wiki"]/div[1]')
and I need the stylesheets in order to display it correctly. They are included in the header like so:
<!DOCTYPE html>
<html lang="en" class="">
<head>
...
<link href="https://example.com/9f40a.css" media="all" rel="stylesheet" />
<link href="https://example.com/4e5fb.css" media="all" rel="stylesheet" />
...
</head>
...
and their naming can be changed. How do I parse/download local copies of the stylesheets?
Something like this:
require 'open-uri'
doc.css("head link").each do |tag|
link = tag["href"]
next unless link && link.end_with?("css")
File.open("/tmp/#{File.basename(link)}", "w") do |f|
content = open(link) { |g| g.read }
f.write(content)
end
end
I'm not a ruby expert but you can go over following steps
You can use .scan(...) method provided with String type to parse and get the .css file names. The scan method will return you an array stylesheet file names. Find more info on scan here
Then download and store the files with Net::HTTP.get(...) an example is here
Admittedly silly-seeming question... And...
before anyone hastily replies, "RTFM," I have yet I still don't quite grok it -- data-binding.
So, I've got a sort of form, which is really a component consisting of inputs and whatnot and also a core-localstorage element. I've successfully persisted the values of other inputs between sessions, yet I've gotten fuzzy on the paper-dropdown-menu. gridlocked...
What I want to do is use the label for the display value, and when the machine in machines bit is going, I want the selected paper-item to reflect the value from local storage (the label)
Oh, and this is in jade, btw. Here's how it's looking:
//- JADE
/** Stuff that works: **/
core-localstorage(id='storage', name='vbms-user-settings', value='{{settings}}')
.subhead General
paper-input(floatingLabel, label='Username', inputValue='{{settings.username}}', on-change='{{updateStorage}}')
paper-input(floatingLabel, label='Password', inputValue='{{settings.password}}', on-change='{{updateStorage}}', type='password')
paper-checkbox#vpn_gui_toggle.accent(label='Run Headless', checked, style='margin-right: 16px;')
/** The confusing input **/
paper-dropdown-menu#vm_dropdown(valueattr='label', on-core-select='{{updateDefaultVM}}')
template(repeat="{{machine in machines}}")
paper-item(label="{{machine.name}}")
Here's some js... this works fine; i'm trying to do things the "dogmatic" Polymer way.
/*\ JS
|*| ...blah blah polymer jank...
\*/
objectToStorage: function(obj) {
this.$.storage.value=obj;
this.$.storage.save();
},
updateStorage: function() {
this.objectToStorage(this.settings);
},
updateDefaultVM: function() {}
Can anyone lead me to the most-probably simple solution to this hangup?!
Thanks in advance!
I believe that the recommended way of using <paper-dropdown-menu> is to have a two layers of containers between it and the <paper-item>s, based on the example from the current docs.
If you're using that setup, you've now got a <core-menu>, which inherits from <core-selector>. Things that inherit from <core-selector> can make use of the selected attribute to control which item is selected. But <core-selected> defaults to checking to see if any of the items it contains has a name attribute whose value matches the selected value, so we also need to add in name attributes to all of the <paper-item>s.
The end result of something simple, that doesn't rely on loading in values from <core-localstorage>, looks like the following. You should be able to do something similar if you're loading in the initial value from <core-localstorage> instead of hardcoding it.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Polymer Demo</title>
</head>
<body>
<script src="//www.polymer-project.org/webcomponents.js"></script>
<link rel="import" href="//www.polymer-project.org/components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="//www.polymer-project.org/components/paper-dropdown/paper-dropdown.html">
<link rel="import" href="//www.polymer-project.org/components/core-menu/core-menu.html">
<link rel="import" href="//www.polymer-project.org/components/paper-item/paper-item.html">
<template id="page-template" is="auto-binding">
<h1>Pastry Menu</h1>
<paper-dropdown-menu label="Your favorite pastry">
<paper-dropdown class="dropdown">
<core-menu class="menu" selected="{{initiallySelected}}">
<template repeat="{{pastry in pastries}}">
<paper-item name="{{pastry}}">{{pastry}}</paper-item>
</template>
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
</template>
<script>
var pageTemplate = document.querySelector('#page-template');
pageTemplate.pastries = [
'Croissant',
'Donut',
'Financier',
'Madeleine'
];
// Set this to whatever you want the initially selected item to be. It's value can be loaded from localStorage.
pageTemplate.initiallySelected = 'Financier';
</script>
</body>
</html>