Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

custom-text-input-column.blade.php 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. @php
  2. use Filament\Support\Enums\Alignment;
  3. $isDisabled = $isDisabled();
  4. $state = $getState();
  5. $mask = $getMask();
  6. $isDeferred = $isDeferred();
  7. $isNavigable = $isNavigable();
  8. $alignment = $getAlignment() ?? Alignment::Start;
  9. if (! $alignment instanceof Alignment) {
  10. $alignment = filled($alignment) ? (Alignment::tryFrom($alignment) ?? $alignment) : null;
  11. }
  12. if (filled($mask)) {
  13. $type = 'text';
  14. } else {
  15. $type = $getType();
  16. }
  17. @endphp
  18. <div
  19. x-data="{
  20. error: undefined,
  21. isEditing: false,
  22. isLoading: false,
  23. name: @js($getName()),
  24. recordKey: @js($recordKey),
  25. state: @js($state),
  26. navigateToRow(direction) {
  27. const currentRow = $el.closest('tr');
  28. const currentCell = $el.closest('td');
  29. const currentColumnIndex = Array.from(currentRow.children).indexOf(currentCell);
  30. const targetRow = direction === 'next'
  31. ? currentRow.nextElementSibling
  32. : currentRow.previousElementSibling;
  33. if (targetRow && targetRow.children[currentColumnIndex]) {
  34. const targetInput = targetRow.children[currentColumnIndex].querySelector('input[x-model=\'state\']');
  35. if (targetInput) {
  36. targetInput.focus();
  37. targetInput.select();
  38. }
  39. }
  40. },
  41. navigateToColumn(direction) {
  42. const currentCell = $el.closest('td');
  43. const currentRow = $el.closest('tr');
  44. const currentColumnIndex = Array.from(currentRow.children).indexOf(currentCell);
  45. const targetCell = direction === 'next'
  46. ? currentRow.children[currentColumnIndex + 1]
  47. : currentRow.children[currentColumnIndex - 1];
  48. if (targetCell) {
  49. const targetInput = targetCell.querySelector('input[x-model=\'state\']');
  50. if (targetInput) {
  51. targetInput.focus();
  52. targetInput.select();
  53. }
  54. }
  55. }
  56. }"
  57. x-init="
  58. () => {
  59. Livewire.hook('commit', ({ component, commit, succeed, fail, respond }) => {
  60. succeed(({ snapshot, effect }) => {
  61. $nextTick(() => {
  62. if (component.id !== @js($this->getId())) {
  63. return
  64. }
  65. if (isEditing) {
  66. return
  67. }
  68. if (! $refs.newState) {
  69. return
  70. }
  71. let newState = $refs.newState.value.replaceAll('\\'+String.fromCharCode(34), String.fromCharCode(34))
  72. if (state === newState) {
  73. return
  74. }
  75. state = newState
  76. })
  77. })
  78. })
  79. }
  80. "
  81. {{
  82. $attributes
  83. ->merge($getExtraAttributes(), escape: false)
  84. ->class([
  85. 'fi-ta-text-input w-full min-w-36',
  86. 'px-3 py-4' => ! $isInline(),
  87. ])
  88. }}
  89. >
  90. <input
  91. type="hidden"
  92. value="{{ str($state)->replace('"', '\\"') }}"
  93. x-ref="newState"
  94. />
  95. <x-filament::input.wrapper
  96. :alpine-disabled="'isLoading || ' . \Illuminate\Support\Js::from($isDisabled)"
  97. alpine-valid="error === undefined"
  98. x-tooltip="
  99. error === undefined
  100. ? false
  101. : {
  102. content: error,
  103. theme: $store.theme,
  104. }
  105. "
  106. x-on:click.stop.prevent=""
  107. >
  108. {{-- format-ignore-start --}}
  109. <x-filament::input
  110. :disabled="$isDisabled"
  111. :input-mode="$getInputMode()"
  112. :placeholder="$getPlaceholder()"
  113. :step="$getStep()"
  114. :type="$type"
  115. :x-bind:disabled="$isDisabled ? null : 'isLoading'"
  116. x-model="state"
  117. x-on:blur="isEditing = false"
  118. x-on:focus="isEditing = true"
  119. :attributes="
  120. \Filament\Support\prepare_inherited_attributes(
  121. $getExtraInputAttributeBag()
  122. ->merge([
  123. 'x-on:change' . ($type === 'number' ? '.debounce.1s' : null) => $isDeferred ? '
  124. $wire.handleBatchColumnChanged({
  125. name: name,
  126. recordKey: recordKey,
  127. value: $event.target.value
  128. })
  129. ' : '
  130. isLoading = true
  131. const response = await $wire.updateTableColumnState(
  132. name,
  133. recordKey,
  134. $event.target.value,
  135. )
  136. error = response?.error ?? undefined
  137. if (! error) {
  138. state = response
  139. }
  140. isLoading = false
  141. ',
  142. 'x-on:keydown.enter' => $isDeferred ? '
  143. $wire.handleBatchColumnChanged({
  144. name: name,
  145. recordKey: recordKey,
  146. value: state
  147. });
  148. $nextTick(() => {
  149. $wire.saveBatchChanges();
  150. });
  151. ' : ($isNavigable ? 'navigateToRow(\'next\')' : null),
  152. 'x-on:keydown.arrow-down.prevent' => $isNavigable ? 'navigateToRow(\'next\')' : null,
  153. 'x-on:keydown.arrow-up.prevent' => $isNavigable ? 'navigateToRow(\'prev\')' : null,
  154. 'x-on:keydown.arrow-left.prevent' => $isNavigable ? 'navigateToColumn(\'prev\')' : null,
  155. 'x-on:keydown.arrow-right.prevent' => $isNavigable ? 'navigateToColumn(\'next\')' : null,
  156. 'x-mask' . ($mask instanceof \Filament\Support\RawJs ? ':dynamic' : '') => filled($mask) ? $mask : null,
  157. ])
  158. ->class([
  159. match ($alignment) {
  160. Alignment::Start => 'text-start',
  161. Alignment::Center => 'text-center',
  162. Alignment::End => 'text-end',
  163. Alignment::Left => 'text-left',
  164. Alignment::Right => 'text-right',
  165. Alignment::Justify, Alignment::Between => 'text-justify',
  166. default => $alignment,
  167. },
  168. ])
  169. )
  170. "
  171. />
  172. {{-- format-ignore-end --}}
  173. </x-filament::input.wrapper>
  174. </div>