Skip to content

Commit 77ee267

Browse files
authored
Merge pull request #57 from takielias/fix
Fix Tom Select
2 parents 3e6d54d + 6d57942 commit 77ee267

File tree

2 files changed

+117
-19
lines changed

2 files changed

+117
-19
lines changed

resources/views/components/forms/inputs/dependent-select.blade.php

Lines changed: 114 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
@php
2+
// Generate a unique ID if one isn't provided
3+
$id = $id ?? 'select-' . uniqid();
4+
@endphp
5+
16
<select name="{{ $name }}"
27
{{ $attributes->merge(['class' => 'form-select']) }}
38
id="{{ $id }}"
@@ -23,43 +28,133 @@
2328
</select>
2429
<div class="invalid-feedback"></div>
2530

31+
@push('css')
32+
<style>
33+
/* Fix for Tom Select dropdown visibility in Tabler */
34+
.ts-dropdown {
35+
/* Use Tabler's surface background color for the dropdown */
36+
background-color: var(--tblr-bg-surface);
37+
/* Add a border to match Tabler's style */
38+
border: 1px solid var(--tblr-border-color);
39+
/* Add a shadow for depth */
40+
box-shadow: var(--tblr-box-shadow);
41+
/* Ensure the dropdown appears above other page content */
42+
z-index: 1050;
43+
}
44+
.ts-dropdown .dropdown-content,
45+
.ts-dropdown .ts-dropdown-content {
46+
/* Ensure the dropdown content itself is not transparent */
47+
background-color: var(--tblr-bg-surface);
48+
}
49+
.ts-dropdown .option {
50+
/* Set text color for options */
51+
color: var(--tblr-body-color);
52+
}
53+
.ts-dropdown .option.active {
54+
/* Style for the active/hovered option */
55+
background-color: var(--tblr-primary-bg-subtle);
56+
color: var(--tblr-primary);
57+
}
58+
</style>
59+
@endpush
60+
2661
@push('js')
2762
<script type="module">
2863
document.addEventListener('DOMContentLoaded', () => {
29-
const mainSelect = document.getElementById('{{ $id }}');
30-
@if($targetDropdown!=null)
31-
const targetSelect = document.getElementById('{{ $targetDropdown }}');
32-
@endif
64+
// Check if TomSelect is available
65+
if (!window.TomSelect) return;
66+
67+
// Initialize Tom Select with Tabler-compatible settings
68+
const mainSelect = new TomSelect('#{{ $id }}', {
69+
copyClassesToDropdown: false,
70+
dropdownParent: 'body',
71+
controlInput: '<input>',
72+
create: false,
73+
sortField: {
74+
field: "text",
75+
direction: "asc"
76+
},
77+
render: {
78+
item: function (data, escape) {
79+
if (data.customProperties) {
80+
return '<div><span class="dropdown-item-indicator">' + data.customProperties + "</span>" + escape(data.text) + "</div>";
81+
}
82+
return "<div>" + escape(data.text) + "</div>";
83+
},
84+
option: function (data, escape) {
85+
if (data.customProperties) {
86+
return '<div><span class="dropdown-item-indicator">' + data.customProperties + "</span>" + escape(data.text) + "</div>";
87+
}
88+
return "<div>" + escape(data.text) + "</div>";
89+
},
90+
}
91+
});
92+
3393
@if($targetDropdown!=null)
34-
mainSelect.addEventListener('change', () => {
94+
const targetSelect = new TomSelect('#{{ $targetDropdown }}', {
95+
copyClassesToDropdown: false,
96+
dropdownParent: 'body',
97+
controlInput: '<input>',
98+
create: false,
99+
sortField: {
100+
field: "text",
101+
direction: "asc"
102+
},
103+
render: {
104+
item: function (data, escape) {
105+
if (data.customProperties) {
106+
return '<div><span class="dropdown-item-indicator">' + data.customProperties + "</span>" + escape(data.text) + "</div>";
107+
}
108+
return "<div>" + escape(data.text) + "</div>";
109+
},
110+
option: function (data, escape) {
111+
if (data.customProperties) {
112+
return '<div><span class="dropdown-item-indicator">' + data.customProperties + "</span>" + escape(data.text) + "</div>";
113+
}
114+
return "<div>" + escape(data.text) + "</div>";
115+
},
116+
}
117+
});
118+
119+
mainSelect.on('change', () => {
35120
@if($targetDataRoute!=null)
36-
targetSelect.dispatchEvent(new CustomEvent('optionsRemoved'));
121+
// Clear existing options in Tom Select
122+
targetSelect.clear();
123+
targetSelect.clearOptions();
124+
125+
// Trigger optionsRemoved event for any child dropdowns
126+
targetSelect.trigger('optionsRemoved');
37127
@endif
128+
38129
axios.get(`{{ route($targetDataRoute) }}`, {
39-
params: {id: mainSelect.value}
130+
params: {id: mainSelect.getValue()}
40131
})
41132
.then(response => {
42-
// The response data is now an object, not an array
43133
const products = response.data;
134+
44135
Object.entries(products).forEach(([id, value]) => {
45-
const opt = document.createElement('option');
46-
opt.value = id;
47-
opt.textContent = value;
48-
targetSelect.appendChild(opt);
136+
targetSelect.addOption({
137+
value: id,
138+
text: value
139+
});
49140
});
141+
142+
targetSelect.refreshOptions();
50143
})
51144
.catch(error => {
52145
console.error('Error fetching data:', error);
53146
});
54147
});
55-
targetSelect.addEventListener('optionsRemoved', function () {
56-
while (this.options.length > 0) {
57-
this.remove(0);
58-
}
59-
const childId = this.dataset.child;
148+
149+
targetSelect.on('optionsRemoved', () => {
150+
const childId = targetSelect.input.dataset.child;
60151
if (childId) {
61-
const childSelect = document.getElementById(childId);
62-
childSelect.dispatchEvent(new CustomEvent('optionsRemoved'));
152+
const childSelect = document.getElementById(childId).tomselect;
153+
if (childSelect) {
154+
childSelect.clear();
155+
childSelect.clearOptions();
156+
childSelect.trigger('optionsRemoved');
157+
}
63158
}
64159
});
65160
@endif

src/Fields/TomSelectField.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
use Illuminate\Support\Facades\View;
66
use Illuminate\View\ComponentAttributeBag;
77
use TakiElias\TablarKit\Components\Forms\Inputs\TomSelect;
8+
use TakiElias\TablarKit\Traits\FieldTrait;
89

910
class TomSelectField extends BaseField
1011
{
12+
use FieldTrait;
13+
1114
protected bool $remoteData = false;
1215
protected ?string $itemSearchRoute = null;
1316

0 commit comments

Comments
 (0)