-1

I have the following in my Go's template.

<button type="submit" class="validate_button" onclick="validate({{.Quiz.ID}})">Validate</button>

This is not working and I am getting this Javascript error :

"Property assignment expected."

This works perfectly of course :

<button type="submit" class="validate_button" onclick="validate(1234)">Validate</button>

Whats the right syntax here?

Note :

I am using VS Code. The same is telling me there is an error but I can compile just fine. The thing is once I ran the app there is no "button" on the page. It simply disappears. It works correctly when I hardcode a value though.

Note 2 :

This is the ouput of executing my template :

2020/02/13 09:52:49 template: execute.html:38:79: executing "execute.html" at <.Quiz.ID>: can't evaluate field Quiz in type models.Question

This is my template :

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Linux Quiz</title>
    <meta name="description" content="Linux Quiz">
    <meta name="author" content="Matias Barrios">
    <link rel="stylesheet" href="static/executeQuizz/style.css">
    <link rel="stylesheet" href="static/style.css">
    <link rel="stylesheet" href="static/bootstrap/css/bootstrap.css">
    <script src="static/bootstrap/js/bootstrap.min.js"></script>
    <script src="static/executeQuizz/main.js"></script>
</head>

<body>
    <div class="topnav">
        <a class="active" href="/index">Home</a>
        <a href="/logout" class="righty" ><div>Logout : <b>{{ .User.Name }}</b></div></a>
        <a href="/contact" class="righty" >Contact</a>
        <a href="/about" class="righty" >About</a>
    </div>
    <div class="title_and_description" >
        <h5> {{ .Quiz.ID }} </h5>
        <h6> {{ .Quiz.Description }} </h6>
    </div>
   {{range $q := .Quiz.Questions}} 
    <div class="question_container">
        <p><h4>{{ $q.Question }}</h4></p>
        {{ $mode := $q.Mode }} {{ if eq $mode "single" }}
            {{range $o := $q.Options}}
            <input type="radio" id="{{ $q.ID }}" name="{{ $q.ID }}" value="{{$o}}">
            <label for="{{ $q.ID }}">{{$o}}</label><br>
            {{end}}
        {{ end}}
    </div>
    <div class="validate_quiz">
        <button type="submit" class="validate_button" onclick="validate({{.Quiz.ID}})">Validate</button>
    </div>
   {{ end }}
</body>

</html>

And this is the execution of the template :

func executeQuizzHanlder(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/execute" && r.Method != "GET" {
        errorHandler(w, r, http.StatusNotFound)
        return
    }
    claims := getClaims(w, r)
    u := models.User{
        Name: claims.Username,
    }
    keys, ok := r.URL.Query()["quizz"]
    if !ok || len(keys) < 1 || len(keys[0]) < 1 {
        errorHandler(w, r, http.StatusNotFound)
        return
    }
    quizz, err := quizzes.GetQuizzByID(keys[0])
    if err != nil {
        errorHandler(w, r, http.StatusNotFound)
        return
    }
    quizz.ID = keys[0]
    envelope := models.ExecuteQuizzEnvelope{
        User: u,
        Quiz: quizz,
    }

    err = views.ViewExecuteQuizz.Execute(w, &envelope)
    log.Println(err.Error())
}

And this is my models :

package models

// Question :
type Question struct {
    ID       string   `json:"id"`
    Mode     string   `json:"mode"`
    Question string   `json:"question"`
    Options  []string `json:"options"`
    Answers  []string `json:"answers"`
}

// Quiz :
type Quiz struct {
    ID          string     `json:"id"`
    Description string     `json:"description"`
    Author      string     `json:"author"`
    Questions   []Question `json:"questions"`
    Completed   bool       `json:"-"`
}

// ExecuteQuizzEnvelope :
type ExecuteQuizzEnvelope struct {
    User User
    Quiz Quiz
}
Matias Barrios
  • 4,674
  • 3
  • 22
  • 49
  • 1
    What is the output from executing the template? – Charlie Tumahai Feb 12 '20 at 19:31
  • Nothing. The app compiles but the button is not visible in the page. If I inspect the page there is not "button" anymore. Like if the template engine gave up and forgot about the button. It does show up if I directly hard code a value like 1234 – Matias Barrios Feb 12 '20 at 19:36
  • Not what's rendered by the browser, what's the actual output from executing the template? – Adrian Feb 12 '20 at 19:49
  • 2
    Also where's the code that executes the template? – Adrian Feb 12 '20 at 19:51
  • 2
    If there is no output from executing the template, then there was probably an error executing the template. What is the error returned from the Execute method? – Charlie Tumahai Feb 12 '20 at 19:57
  • 1
    @MatiasBarrios as you can see here https://play.golang.com/p/apP42ZUhLAB there's nothing wrong with the small piece of template that you've included in the question. The problem is either in your Go code or in the part of the template that you've omitted. When asking questions on SO, you should strive to provide a [minimal, complete, and verifiable example](https://stackoverflow.com/help/minimal-reproducible-example). – mkopriva Feb 12 '20 at 21:07
  • @mkopriva I have added relevant code now. – Matias Barrios Feb 13 '20 at 12:57
  • @Adrian I have added relevant code now – Matias Barrios Feb 13 '20 at 12:57
  • @CeriseLimón I have added relevant code now – Matias Barrios Feb 13 '20 at 12:58
  • @MatiasBarrios in go templates when you range over a value, like `.Quiz.Questions`, the `.` inside that range block is set to the iteration element, i.e. `.` is set to `Question` inside `range := .Quiz.Questions` which is why you get that error. To get the "top" value passed to the template, the `ExecuteQuizzEnvelope` instance, use the `$.` , i.e. `$.Quiz.ID`. – mkopriva Feb 13 '20 at 13:02
  • ... this is mentioned in the package's documentation on [Variables](https://golang.org/pkg/text/template/) *"When execution begins, $ is set to the data argument passed to Execute, that is, to the starting value of dot."* – mkopriva Feb 13 '20 at 13:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/207761/discussion-between-matias-barrios-and-mkopriva). – Matias Barrios Feb 13 '20 at 13:11

1 Answers1

1

Thanks to everybody for replying. As @mkopriva stated, within a range the . is set to the iteration element. I initially thought that this syntax...

{{range $o := $q.Options}}

would avoid that since I am naming my iteration variable o, but I was wrong in my assumption.

So that was the problem in this case.

Matias Barrios
  • 4,674
  • 3
  • 22
  • 49