Home > Enterprise >  Can not manipulate DOM from template to add/remove attribute
Can not manipulate DOM from template to add/remove attribute

Time:11-11

In my code, I want to disable some inputs fields based on the user authentication level, I was able to do it in JavaScript, but this is unrecommended solution, and I want to make it from the server side.

Below is my go code;

package main

import (
    "context"
    "html/template"
    "net/http"
    "strings"
    "time"
)

type User struct {
    Flags string
    Title string
}

type UsersPageData struct {
    PageTitle string
    Users     []User
}

func requestTime(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()
        ctx = context.WithValue(ctx, "requestTime", time.Now().Format(time.RFC3339))
        r = r.WithContext(ctx)
        next.ServeHTTP(w, r)
    })
}

func helloHandler(name string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        var title string
        if requestTime := r.Context().Value("requestTime"); requestTime != nil {
            if str, ok := requestTime.(string); ok {
                title = "\ngenerated at: "   str
            }
        }

        master := strings.Join([]string{"admin", "user", "superuser", "read"}, " ")
        admin := strings.Join([]string{"admin"}, " ")
        user := strings.Join([]string{"user"}, " ")

        tmpl := template.Must(template.ParseFiles("index.html"))
        data := UsersPageData{
            PageTitle: "Users list: "   title,
            Users: []User{
                {Flags: master, Title: "Everything"},
                {Flags: admin, Title: "Administrator"},
                {Flags: user, Title: "Normal user"},
            },
        }
        tmpl.Execute(w, data)
    })
}

func main() {
    http.Handle("/john", requestTime(helloHandler("John")))
    http.ListenAndServe(":8080", nil)
}

And here is my template including the JS code;

<style>
.admin {
    color: green;
}

.user {
    color: red;
    --btn-disable: 0;
}


[data-authorized="no"] {
  /* Attribute has this exact value */
        cursor: not-allowed;
        pointer-events: none;

        /*Button disabled - CSS color class*/
        color: #c0c0c0;
        background-color: rgb(229, 229, 229) !important;
}

</style>
<h1>{{.PageTitle}}</h1>
<ul>
    {{range .Users}}
            <input type="text" data-permissions={{.Flags}} data-authorized="no">{{.Title}}</s>
    {{end}}
</ul>

<script>
  var flags = ["admin", "super user"]
  var elements = document.querySelectorAll("input");
  elements.forEach((element, index, array) => { 
        if(element.hasAttribute("data-permissions")){
            console.log(element.dataset.permissions)
            var perm = element.dataset.permissions.split(" ");
                    var found = false;
                    for (var i = 0; i < perm.length; i  ) {
                        if (flags.indexOf(perm[i]) > -1) {
                            element.dataset.authorized = "yes"
                            element.removeAttribute("data-permissions")
                            break;
                        }
                    } 
        }
  });
</script>

And here is the output: enter image description here

Any thought?

CodePudding user response:

I was able to do it, with the help of template custom functions, below the full code:

package main

import (
    "html/template"
    "net/http"
)

type User struct {
    Flags []flag //string
    Title string
}

type UsersPageData struct {
    PageTitle string
    Users     []User
}

type flag int

const (
    Admin flag = iota   1 // iota = 0
    Editer
    Superuser
    Viewer
    Dummy
)

func subtract(arg1, arg2 int) int {
    return arg1 - arg2
}

func helloHandler(name string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Map the `subtract` custom function in the template
        funcMap := map[string]interface{}{"subtract": subtract}

        master := []flag{Admin, Editer, Superuser, Viewer}
        admin := []flag{Admin, Superuser, Viewer}
        user := []flag{Viewer, Dummy}

        tmpl := template.New("").Funcs(template.FuncMap(funcMap))
        template.Must(tmpl.ParseFiles("index.html"))
        data := UsersPageData{
            PageTitle: "Users list: ",
            Users: []User{
                {Flags: master, Title: "Everything"},
                {Flags: admin, Title: "Administrator"},
                {Flags: user, Title: "Normal user"},
            },
        }
        tmpl.ExecuteTemplate(w, "index.html", data)
    })
}

func main() {
    fs := http.StripPrefix("/www/", http.FileServer(http.Dir("./www")))
    http.Handle("/www/", fs)

    http.Handle("/", helloHandler("John"))
    http.ListenAndServe(":8080", nil)
}

The index.html is:

<html>
{{/* This is a comment 
{{$flags := []flag{Admin, Editer, Superuser, Viewer};}} 
    Admin Flag = iota   1 // iota = 0
    Editer
    Superuser
    Viewer
    }}
*/}}

<ul>
    {{range .Users}}
        <span>{{.Title}}</span>
        {{ $done := false}} {{$length := len .Flags}}
        {{range $i, $v := .Flags}}
            {{ if $done }}
            {{ else }}
                {{if or (eq $v 1) (eq $v 3)}} 
                    <input type="text" name="subject" placeholder= {{$v}} required>
                    {{ $done = true }}
                {{else}}
                    {{ if eq $i (subtract $length 1)}}
                        <input type="text" name="subject" placeholder= {{$v}} disabled>
                    {{ end }}
                {{end}}
            {{end}}
        {{end}}
    {{end}}
</ul>
</html>

enter image description here

  •  Tags:  
  • go
  • Related