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:
parent
5702f0d198
commit
f93d557aa9
|
@ -588,11 +588,6 @@ main > nav {
|
|||
right: 0;
|
||||
}
|
||||
|
||||
/* AlpineJS */
|
||||
[x-cloak] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Multiselect */
|
||||
.multiselect {
|
||||
max-width: 35rem;
|
||||
|
|
|
@ -6,13 +6,6 @@
|
|||
<title>{{ template "title" . }} — Numerus</title>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="/static/numerus.css">
|
||||
<script defer src="/static/alpinejs@3.12.0.min.js"></script>
|
||||
<noscript>
|
||||
<style>
|
||||
[x-cloak] {
|
||||
display: revert !important;
|
||||
}
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
|
|
|
@ -40,7 +40,21 @@
|
|||
|
||||
{{ define "select-field" -}}
|
||||
{{- /*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 }}"
|
||||
{{- range $attribute := .Attributes }} {{$attribute}} {{ end -}}
|
||||
{{ if .Multiple }} multiple="multiple"{{ end -}}
|
||||
|
@ -65,6 +79,30 @@
|
|||
</optgroup>
|
||||
{{- end }}
|
||||
</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>
|
||||
{{- if .Errors }}
|
||||
<ul>
|
||||
|
|
|
@ -20,58 +20,7 @@
|
|||
{{ template "input-field" .Name | addInputAttr "autofocus" }}
|
||||
{{ template "input-field" .Description }}
|
||||
{{ 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 }}
|
||||
</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>
|
||||
{{ template "select-field" .Tax }}
|
||||
|
||||
<fieldset>
|
||||
<button class="primary" type="submit">{{( pgettext "Update product" "action" )}}</button>
|
||||
|
|
Loading…
Reference in New Issue