检查项目是否存在以及是真还是假
Check if item exist and is true or false
在我的代码中,我将结构 ReturnedResult
发送到模板:
type ReturnedResult struct {
Result bool `json:"result"`
Message string `json:"message"`
}
我希望模板:
- 检查是否有
Result
或nil
- 如果有一个
Result
我想看看是true
还是false
所以,我写了以下内容:
{{with .Result}}
{{if .Result}}
<div id='foo'>
<i class="far fa-thumbs-up"></i>If report not opened automatically, pls download from <a href={{.Message}}>here</a>
</div>
<script>
url = `{{.Message}}`
window.open(url, "_blank");
setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
</script>
{{else}}
<i class="fas fa-exclamation-triangle">{{.Message}}</i>>
<script>
setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
</script>
{{end}}
{{end}}
有时我将不带数据的模板称为 tmpl.Execute(w, nil)
,有时将带数据的模板称为 tmpl.Execute(w, webReturn)
没有数据的可以正常使用,但是有数据的就不行,不知道哪里出了问题。
如果需要,下面是我的完整代码。
// go build -ldflags "-H=windowsgui"
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"text/template"
"github.com/zserge/lorca"
)
// ContactDetails ...
type ContactDetails struct {
Email string
Subject string
Message string
Color1 []string
Color2 []string
}
// ReturnedResult ...
type ReturnedResult struct {
Result bool `json:"result"`
Message string `json:"message"`
}
func index(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("forms.html"))
if r.Method != http.MethodPost {
tmpl.Execute(w, nil)
return
}
r.ParseForm()
fmt.Println(r.Form) // print information on server side.
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["color1"][0])
fmt.Println(r.Form["color1"][1])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
details := ContactDetails{
Email: r.FormValue("email"),
Subject: r.FormValue("subject"),
Message: r.FormValue("message"),
Color1: r.Form["color1"],
Color2: r.Form["color2"],
}
fmt.Printf("Post from website! r.PostFrom = %v\n", r.PostForm)
fmt.Printf("Details = %v\n", details)
//r.FormValue("username")
fmt.Println()
// do something with details
sheetID := "AKfycbxfMucXOzX15tfU4errRSAa9IzuTRbHzvUdRxzzeYnNA8Ynz8LJuBuaMA/exec"
url := "https://script.google.com/macros/s/" + sheetID + "/exec"
bytesRepresentation, err := json.Marshal(details)
if err != nil {
log.Fatalln(err)
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(bytesRepresentation))
if err != nil {
log.Fatalln(err)
}
// read all response body
data, _ := ioutil.ReadAll(resp.Body)
// close response body
resp.Body.Close()
webReturn := ReturnedResult{}
if err := json.Unmarshal([]byte(data), &webReturn); err != nil {
panic(err)
}
fmt.Println(webReturn.Message)
webReturn.Message = strings.ReplaceAll(webReturn.Message, "&export=download", "")
//tmpl.Execute(w, struct{ Success bool }{webReturn.Result})
tmpl.Execute(w, webReturn)
}
func main() {
// Start Host goroutine
go func() {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./public"))))
http.HandleFunc("/", index)
http.ListenAndServe(":8090", nil)
}()
// Start UI
ui, err := lorca.New("http://localhost:8090/index", "", 1200, 800)
if err != nil {
log.Fatal(err)
}
defer ui.Close()
<-ui.Done()
}
模板;
<title>Form Submittal</title>
<style>
body {
font-family: Ubuntu, "times new roman", times, roman, serif;
}
</style>
<link href="http://localhost:8090/static/fontawesome-free-5.15.2-web/css/all.css" rel="stylesheet"> <!--load all styles -->
<!-- link rel="stylesheet" href="http://localhost:8090/styles/MaterialDesign-Webfont-master/css/materialdesignicons.min.css" -->
<script type="module" src="http://localhost:8090/static/node_modules/@mdi/js/mdi.js"></script>
<script type="module">
// import {mdi-home} from "./node_modules/@mdi/js/mdi.js";
// alert(a);
</script>
<script>
//import { mdi-home } from '/MaterialDesign-JS-master/mdi.js';
function deleteRow(row) {
var i = row.parentNode.parentNode.rowIndex - 2; // this -> td -> tr // -2 because the first 2 rows are used for header
var tbl = document.querySelector('tbody');
if(tbl && tbl.rows.length > 1) {
tbl.deleteRow(i);
Array.from(tbl.rows).forEach((row, index) => {
row.cells[0].innerHTML = index + 1;
});
}
}
function insRow(row) {
var i = row.parentNode.parentNode.rowIndex - 2; // this -> td -> tr // -2 because the first 2 rows are used for header
var tbl = document.querySelector('tbody');
var row = document.createElement('tr');
row.innerHTML=`
<th></th>
<td><input size=25 type="text" name="color1" /></td>
<td><input size=25 type="text" name="color2" ></td>
<td><i class="fas fa-edit" onclick="insRow(this)"></i></td>
<td><i class="fas fa-eraser" onclick="deleteRow(this)"></i></td>
`;
var len = tbl.rows.length;
row.cells[0].innerHTML = len + 1;
tbl.insertBefore(row, tbl.children[i+1]);
Array.from(tbl.rows).forEach((row, index) => {
row.cells[0].innerHTML = index + 1;
});
//tbl.appendChild(row);
}
</script>
<h1>Contact</h1>
Bob lives in a <span class="mdi mdi-home"></span>.
<form method="POST">
<label>Email:</label><br />
<input type="text" name="email"><br />
<label>Subject:</label><br />
<input type="text" name="subject"><br />
<label>Message:</label><br />
<textarea name="message"></textarea><br />
<table>
<caption>Monthly savings</caption>
<thead>
<tr>
<th colspan="5">The table header</th>
</tr>
<tr>
<th>SN</td>
<th>PO number</td>
<th>PO invoice value</td>
<th colspan="2">Action</td>
</tr>
</thead>
<tbody >
<tr>
<th>1</th>
<td><input size=25 type="text" name="color1" /></td>
<td><input size=25 type="text" name="color2" /></td>
<td colspan="2"><i class="fas fa-edit" onclick="insRow(this)"></i></td>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="5">The table footer</th>
</tr>
</tfoot>
</table>
<input type="submit">
</form>
{{with .Message}}
{{if .Result}}
<div id='foo'>
<i class="far fa-thumbs-up"></i>If report not opened automatically, pls download from <a href={{.Message}}>here</a>
</div>
<script>
url = `{{.Message}}`
window.open(url, "_blank");
setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
</script>
{{else}}
<i class="fas fa-exclamation-triangle">{{.Message}}</i>>
<script>
setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
</script>
{{end}}
{{end}}
template.Execute()
returns 一个 error
, 做 检查:
if err := tmpl.Execute(w, webReturn); err != nil {
// Handle error:
log.Printf("Template error: %v", err)
return
}
这是一个最小的可重现示例:
type ReturnedResult struct {
Result bool
Message string
}
func main() {
t := template.Must(template.New("").Parse(src))
if err := t.Execute(os.Stdout, nil); err != nil {
panic(err)
}
p := ReturnedResult{Result: false, Message: "a"}
if err := t.Execute(os.Stdout, p); err != nil {
panic(err)
}
p = ReturnedResult{Result: true, Message: "a"}
if err := t.Execute(os.Stdout, p); err != nil {
panic(err)
}
}
const src = `{{with .Message}}
{{if .Result}}
Message with true result
{{else }}
Message with false result
{{end}}
{{end}}
`
在 Go Playground 上测试它,输出是:
panic: template: :2:7: executing "" at <.Result>: can't evaluate field Result in type string
goroutine 1 [running]:
main.main()
/tmp/sandbox993188219/prog.go:22 +0x226
问题是 {{with}}
操作设置了点,因此 {{with}}
点内将表示 Message
字段,显然没有 .Result
字段(它不是结构)。
要仅测试(而不是更改点),请使用简单的 {{if}}
:
{{if .Message}}
{{if .Result}}
Message with true result
{{else }}
Message with false result
{{end}}
{{end}}
使用此模板,输出将是(在 Go Playground 上尝试):
<empty output for the nil param>
Message with false result
Message with true result
在我的代码中,我将结构 ReturnedResult
发送到模板:
type ReturnedResult struct {
Result bool `json:"result"`
Message string `json:"message"`
}
我希望模板:
- 检查是否有
Result
或nil - 如果有一个
Result
我想看看是true
还是false
所以,我写了以下内容:
{{with .Result}}
{{if .Result}}
<div id='foo'>
<i class="far fa-thumbs-up"></i>If report not opened automatically, pls download from <a href={{.Message}}>here</a>
</div>
<script>
url = `{{.Message}}`
window.open(url, "_blank");
setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
</script>
{{else}}
<i class="fas fa-exclamation-triangle">{{.Message}}</i>>
<script>
setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
</script>
{{end}}
{{end}}
有时我将不带数据的模板称为 tmpl.Execute(w, nil)
,有时将带数据的模板称为 tmpl.Execute(w, webReturn)
没有数据的可以正常使用,但是有数据的就不行,不知道哪里出了问题。
如果需要,下面是我的完整代码。
// go build -ldflags "-H=windowsgui"
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"text/template"
"github.com/zserge/lorca"
)
// ContactDetails ...
type ContactDetails struct {
Email string
Subject string
Message string
Color1 []string
Color2 []string
}
// ReturnedResult ...
type ReturnedResult struct {
Result bool `json:"result"`
Message string `json:"message"`
}
func index(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("forms.html"))
if r.Method != http.MethodPost {
tmpl.Execute(w, nil)
return
}
r.ParseForm()
fmt.Println(r.Form) // print information on server side.
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["color1"][0])
fmt.Println(r.Form["color1"][1])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
details := ContactDetails{
Email: r.FormValue("email"),
Subject: r.FormValue("subject"),
Message: r.FormValue("message"),
Color1: r.Form["color1"],
Color2: r.Form["color2"],
}
fmt.Printf("Post from website! r.PostFrom = %v\n", r.PostForm)
fmt.Printf("Details = %v\n", details)
//r.FormValue("username")
fmt.Println()
// do something with details
sheetID := "AKfycbxfMucXOzX15tfU4errRSAa9IzuTRbHzvUdRxzzeYnNA8Ynz8LJuBuaMA/exec"
url := "https://script.google.com/macros/s/" + sheetID + "/exec"
bytesRepresentation, err := json.Marshal(details)
if err != nil {
log.Fatalln(err)
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(bytesRepresentation))
if err != nil {
log.Fatalln(err)
}
// read all response body
data, _ := ioutil.ReadAll(resp.Body)
// close response body
resp.Body.Close()
webReturn := ReturnedResult{}
if err := json.Unmarshal([]byte(data), &webReturn); err != nil {
panic(err)
}
fmt.Println(webReturn.Message)
webReturn.Message = strings.ReplaceAll(webReturn.Message, "&export=download", "")
//tmpl.Execute(w, struct{ Success bool }{webReturn.Result})
tmpl.Execute(w, webReturn)
}
func main() {
// Start Host goroutine
go func() {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./public"))))
http.HandleFunc("/", index)
http.ListenAndServe(":8090", nil)
}()
// Start UI
ui, err := lorca.New("http://localhost:8090/index", "", 1200, 800)
if err != nil {
log.Fatal(err)
}
defer ui.Close()
<-ui.Done()
}
模板;
<title>Form Submittal</title>
<style>
body {
font-family: Ubuntu, "times new roman", times, roman, serif;
}
</style>
<link href="http://localhost:8090/static/fontawesome-free-5.15.2-web/css/all.css" rel="stylesheet"> <!--load all styles -->
<!-- link rel="stylesheet" href="http://localhost:8090/styles/MaterialDesign-Webfont-master/css/materialdesignicons.min.css" -->
<script type="module" src="http://localhost:8090/static/node_modules/@mdi/js/mdi.js"></script>
<script type="module">
// import {mdi-home} from "./node_modules/@mdi/js/mdi.js";
// alert(a);
</script>
<script>
//import { mdi-home } from '/MaterialDesign-JS-master/mdi.js';
function deleteRow(row) {
var i = row.parentNode.parentNode.rowIndex - 2; // this -> td -> tr // -2 because the first 2 rows are used for header
var tbl = document.querySelector('tbody');
if(tbl && tbl.rows.length > 1) {
tbl.deleteRow(i);
Array.from(tbl.rows).forEach((row, index) => {
row.cells[0].innerHTML = index + 1;
});
}
}
function insRow(row) {
var i = row.parentNode.parentNode.rowIndex - 2; // this -> td -> tr // -2 because the first 2 rows are used for header
var tbl = document.querySelector('tbody');
var row = document.createElement('tr');
row.innerHTML=`
<th></th>
<td><input size=25 type="text" name="color1" /></td>
<td><input size=25 type="text" name="color2" ></td>
<td><i class="fas fa-edit" onclick="insRow(this)"></i></td>
<td><i class="fas fa-eraser" onclick="deleteRow(this)"></i></td>
`;
var len = tbl.rows.length;
row.cells[0].innerHTML = len + 1;
tbl.insertBefore(row, tbl.children[i+1]);
Array.from(tbl.rows).forEach((row, index) => {
row.cells[0].innerHTML = index + 1;
});
//tbl.appendChild(row);
}
</script>
<h1>Contact</h1>
Bob lives in a <span class="mdi mdi-home"></span>.
<form method="POST">
<label>Email:</label><br />
<input type="text" name="email"><br />
<label>Subject:</label><br />
<input type="text" name="subject"><br />
<label>Message:</label><br />
<textarea name="message"></textarea><br />
<table>
<caption>Monthly savings</caption>
<thead>
<tr>
<th colspan="5">The table header</th>
</tr>
<tr>
<th>SN</td>
<th>PO number</td>
<th>PO invoice value</td>
<th colspan="2">Action</td>
</tr>
</thead>
<tbody >
<tr>
<th>1</th>
<td><input size=25 type="text" name="color1" /></td>
<td><input size=25 type="text" name="color2" /></td>
<td colspan="2"><i class="fas fa-edit" onclick="insRow(this)"></i></td>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="5">The table footer</th>
</tr>
</tfoot>
</table>
<input type="submit">
</form>
{{with .Message}}
{{if .Result}}
<div id='foo'>
<i class="far fa-thumbs-up"></i>If report not opened automatically, pls download from <a href={{.Message}}>here</a>
</div>
<script>
url = `{{.Message}}`
window.open(url, "_blank");
setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
</script>
{{else}}
<i class="fas fa-exclamation-triangle">{{.Message}}</i>>
<script>
setTimeout(function () {document.querySelector('#foo').style.display='none'}, 5000);
</script>
{{end}}
{{end}}
template.Execute()
returns 一个 error
, 做 检查:
if err := tmpl.Execute(w, webReturn); err != nil {
// Handle error:
log.Printf("Template error: %v", err)
return
}
这是一个最小的可重现示例:
type ReturnedResult struct {
Result bool
Message string
}
func main() {
t := template.Must(template.New("").Parse(src))
if err := t.Execute(os.Stdout, nil); err != nil {
panic(err)
}
p := ReturnedResult{Result: false, Message: "a"}
if err := t.Execute(os.Stdout, p); err != nil {
panic(err)
}
p = ReturnedResult{Result: true, Message: "a"}
if err := t.Execute(os.Stdout, p); err != nil {
panic(err)
}
}
const src = `{{with .Message}}
{{if .Result}}
Message with true result
{{else }}
Message with false result
{{end}}
{{end}}
`
在 Go Playground 上测试它,输出是:
panic: template: :2:7: executing "" at <.Result>: can't evaluate field Result in type string
goroutine 1 [running]:
main.main()
/tmp/sandbox993188219/prog.go:22 +0x226
问题是 {{with}}
操作设置了点,因此 {{with}}
点内将表示 Message
字段,显然没有 .Result
字段(它不是结构)。
要仅测试(而不是更改点),请使用简单的 {{if}}
:
{{if .Message}}
{{if .Result}}
Message with true result
{{else }}
Message with false result
{{end}}
{{end}}
使用此模板,输出将是(在 Go Playground 上尝试):
<empty output for the nil param>
Message with false result
Message with true result