Move the multiselect “component” to the select-field template

I had in the product edit page only because it was easier to test there
while i was developing it, but it is something that should be done for
all select[multiple], of course.

I removed the whole x-cloak thing because i am not sure what would
happen if i do something wrong and Alpine can not initialize the
multiselect; probably show nothing to the user.  Now it shows the
native select a fraction of a second, but if i fuck it up at least the
user can still use the app.
This commit is contained in:
jordi fita mas 2023-03-15 11:44:18 +01:00
parent 5702f0d198
commit f93d557aa9
4 changed files with 40 additions and 65 deletions

View File

@ -588,11 +588,6 @@ main > nav {
right: 0; right: 0;
} }
/* AlpineJS */
[x-cloak] {
display: none !important;
}
/* Multiselect */ /* Multiselect */
.multiselect { .multiselect {
max-width: 35rem; max-width: 35rem;

View File

@ -6,13 +6,6 @@
<title>{{ template "title" . }} — Numerus</title> <title>{{ template "title" . }} — Numerus</title>
<link rel="stylesheet" type="text/css" media="screen" href="/static/numerus.css"> <link rel="stylesheet" type="text/css" media="screen" href="/static/numerus.css">
<script defer src="/static/alpinejs@3.12.0.min.js"></script> <script defer src="/static/alpinejs@3.12.0.min.js"></script>
<noscript>
<style>
[x-cloak] {
display: revert !important;
}
</style>
</noscript>
</head> </head>
<body> <body>
<header> <header>

View File

@ -40,7 +40,21 @@
{{ define "select-field" -}} {{ define "select-field" -}}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.SelectField*/ -}} {{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.SelectField*/ -}}
<div class="input {{ if .Errors }}has-errors{{ end }}"> <div class="input{{ if .Errors }} has-errors{{ end }}"
{{- if .Multiple }}
x-data="{
options: [
{{- range $option := .Options }}
{ value: '{{ .Value }}', label: '{{ .Label }}', selected: {{ if $.IsSelected .Value }}true{{ else }}false{{ end }} },
{{- end }}
],
open: false,
init() {
$el.querySelector('select').remove();
},
}"
{{- end -}}
>
<select id="{{ .Name }}-field" name="{{ .Name }}" <select id="{{ .Name }}-field" name="{{ .Name }}"
{{- range $attribute := .Attributes }} {{$attribute}} {{ end -}} {{- range $attribute := .Attributes }} {{$attribute}} {{ end -}}
{{ if .Multiple }} multiple="multiple"{{ end -}} {{ if .Multiple }} multiple="multiple"{{ end -}}
@ -65,6 +79,30 @@
</optgroup> </optgroup>
{{- end }} {{- end }}
</select> </select>
{{- if .Multiple }}
<template x-if="true">
<div class="multiselect">
<ul class="tags" :class="{'empty': options.filter(option => option.selected).length === 0}"
@click="open = !open" @click.away="open = false">
<template x-for="(option) in options.filter(option => option.selected)">
<li>
<input type="hidden" name="{{ .Name }}" :value="option.value">
<span x-text="option.label"></span>
<button type="button" @click.stop="option.selected = false">×</button>
</li>
</template>
</ul>
<ul class="options" x-show.transition="open">
<template x-for="(option) in options.filter(option => !option.selected)">
<li
x-text="option.label"
@click.stop="option.selected = true"
></li>
</template>
</ul>
</div>
</template>
{{ end -}}
<label for="{{ .Name }}-field">{{ .Label }}</label> <label for="{{ .Name }}-field">{{ .Label }}</label>
{{- if .Errors }} {{- if .Errors }}
<ul> <ul>

View File

@ -20,58 +20,7 @@
{{ template "input-field" .Name | addInputAttr "autofocus" }} {{ template "input-field" .Name | addInputAttr "autofocus" }}
{{ template "input-field" .Description }} {{ template "input-field" .Description }}
{{ template "input-field" .Price }} {{ template "input-field" .Price }}
<div x-data="{
options: [],
open: false,
init() {
const wrap = $el.querySelector('.input');
const select = wrap.querySelector('select');
for (const option of select.options) {
this.options.push({
value: option.value,
label: option.innerText,
selected: option.getAttribute('selected') !== null,
});
}
wrap.remove();
}
}">
<div x-cloak>
{{ template "select-field" .Tax }} {{ template "select-field" .Tax }}
</div>
{{ with .Tax }}
<template x-if="true">
<div class="input multiselect {{ if .Errors }}has-errors{{ end }}">
<ul class="tags" :class="{'empty': options.filter(option => option.selected).length === 0}"
@click="open = !open" @click.away="open = false">
<template x-for="(option) in options.filter(option => option.selected)">
<li>
<input type="hidden" name="{{ .Name }}" :value="option.value">
<span x-text="option.label"></span>
<button type="button" @click.stop="option.selected = false">×</button>
</li>
</template>
</ul>
<span class="placeholder">{{ .Label }}</span>
<ul class="options" x-show.transition="open">
<template x-for="(option) in options.filter(option => !option.selected)">
<li
x-text="option.label"
@click.stop="option.selected = true"
></li>
</template>
</ul>
{{- if .Errors }}
<ul>
{{- range $error := .Errors }}
<li>{{ . }}</li>
{{- end }}
</ul>
{{- end }}
</div>
</template>
{{ end }}
</div>
<fieldset> <fieldset>
<button class="primary" type="submit">{{( pgettext "Update product" "action" )}}</button> <button class="primary" type="submit">{{( pgettext "Update product" "action" )}}</button>