Skip to content

Commit c4bfb8f

Browse files
pxpmStyleCIBottabacitu
authored
Form component (no ajax form) (#5814)
Co-authored-by: StyleCI Bot <[email protected]> Co-authored-by: Cristian Tabacitu <[email protected]>
1 parent 5087c1d commit c4bfb8f

File tree

9 files changed

+171
-8
lines changed

9 files changed

+171
-8
lines changed

src/CrudPanelManager.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ public function setupCrudPanel(string $controller, ?string $operation = null): C
6969
$crud->setOperation($operation);
7070

7171
$primaryControllerRequest = $this->cruds[array_key_first($this->cruds)]->getRequest();
72-
if (! $crud->isInitialized()) {
72+
if (! $crud->isInitialized() || ! $this->isOperationInitialized($controller::class, $operation)) {
73+
self::setActiveController($controller::class);
74+
$crud->initialized = false;
7375
self::setActiveController($controller::class);
7476
$controller->initializeCrudPanel($primaryControllerRequest, $crud);
7577
self::unsetActiveController();
@@ -81,6 +83,14 @@ public function setupCrudPanel(string $controller, ?string $operation = null): C
8183
return $this->cruds[$controller::class];
8284
}
8385

86+
/**
87+
* Check if a specific operation has been initialized for a controller.
88+
*/
89+
public function isOperationInitialized(string $controller, string $operation): bool
90+
{
91+
return in_array($operation, $this->getInitializedOperations($controller), true);
92+
}
93+
8494
/**
8595
* Record that an operation has been initialized for a controller.
8696
*
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
namespace Backpack\CRUD\app\View\Components;
4+
5+
use Backpack\CRUD\CrudManager;
6+
use Illuminate\View\Component;
7+
8+
class Dataform extends Component
9+
{
10+
public $crud;
11+
12+
/**
13+
* Create a new component instance.
14+
*
15+
* @param string $controller The CRUD controller class name
16+
* @param string $operation The operation to use (create, update, etc.)
17+
* @param string|null $action Custom form action URL
18+
* @param string $method Form method (post, put, etc.)
19+
*/
20+
public function __construct(
21+
public string $controller,
22+
public string $id = 'backpack-form',
23+
public string $operation = 'create',
24+
public ?string $action = null,
25+
public string $method = 'post',
26+
public bool $hasUploadFields = false,
27+
public $entry = null,
28+
29+
) {
30+
// Get CRUD panel instance from the controller
31+
if (CrudManager::hasCrudPanel($controller)) {
32+
$previousOperation = CrudManager::getCrudPanel($controller)->getOperation();
33+
}
34+
35+
$this->crud = CrudManager::setupCrudPanel($controller, $operation);
36+
37+
if (isset($previousOperation)) {
38+
$this->crud->setOperation($previousOperation);
39+
}
40+
41+
if ($this->entry && $this->operation === 'update') {
42+
$this->action = $action ?? url($this->crud->route.'/'.$this->entry->getKey());
43+
$this->method = 'put';
44+
$this->crud->entry = $this->entry;
45+
$this->crud->setOperationSetting('fields', $this->crud->getUpdateFields());
46+
} else {
47+
$this->action = $action ?? url($this->crud->route);
48+
}
49+
$this->hasUploadFields = $this->crud->hasUploadFields($operation, $this->entry?->getKey());
50+
$this->id = $id.md5($this->action.$this->operation.$this->method.$this->controller);
51+
}
52+
53+
/**
54+
* Get the view / contents that represent the component.
55+
*
56+
* @return \Illuminate\Contracts\View\View|\Closure|string
57+
*/
58+
public function render()
59+
{
60+
return view('crud::components.dataform.form', [
61+
'crud' => $this->crud,
62+
'saveAction' => $this->crud->getSaveAction(),
63+
'id' => $this->id,
64+
'operation' => $this->operation,
65+
'action' => $this->action,
66+
'method' => $this->method,
67+
'hasUploadFields' => $this->hasUploadFields,
68+
'entry' => $this->entry,
69+
]);
70+
}
71+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<div class="backpack-form">
2+
@include('crud::inc.grouped_errors', ['id' => $id])
3+
4+
5+
<form method="post"
6+
action="{{ $action }}"
7+
id="{{ $id }}"
8+
@if($hasUploadFields)
9+
enctype="multipart/form-data"
10+
@endif
11+
>
12+
{!! csrf_field() !!}
13+
14+
15+
16+
<input type="hidden" name="_form_id" value="{{ $id }}">
17+
@if($method !== 'post')
18+
@method($method)
19+
@endif
20+
{{-- Include the form fields --}}
21+
@include('crud::form_content', ['fields' => $crud->fields(), 'action' => $operation, 'id' => $id])
22+
23+
{{-- This makes sure that all field assets are loaded. --}}
24+
<div class="d-none" id="parentLoadedAssets">{{ json_encode(Basset::loaded()) }}</div>
25+
26+
@include('crud::inc.form_save_buttons')
27+
</form>
28+
</div>
29+
30+
@push('after_scripts')
31+
<script>
32+
document.addEventListener('DOMContentLoaded', function() {
33+
// Initialize the form fields after loading
34+
if (typeof initializeFieldsWithJavascript === 'function') {
35+
try {
36+
initializeFieldsWithJavascript(document.querySelector('.backpack-form'));
37+
} catch (e) {
38+
console.error('Error initializing form fields:', e);
39+
}
40+
}
41+
42+
// Focus on first focusable field when form is loaded
43+
const form = document.querySelector('.backpack-form form');
44+
if (form) {
45+
const firstField = form.querySelector('input:not([type=hidden]), select, textarea');
46+
if (firstField) {
47+
firstField.focus();
48+
}
49+
}
50+
});
51+
</script>
52+
@endpush

src/resources/views/crud/create.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
<div class="{{ $crud->getCreateContentClass() }}">
3434
{{-- Default box --}}
3535

36-
@include('crud::inc.grouped_errors')
36+
@include('crud::inc.grouped_errors', ['id' => $id])
3737

3838
<form method="post"
3939
action="{{ url($crud->route) }}"

src/resources/views/crud/edit.blade.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<div class="{{ $crud->getEditContentClass() }}">
2929
{{-- Default box --}}
3030

31-
@include('crud::inc.grouped_errors')
31+
@include('crud::inc.grouped_errors', ['id' => $id])
3232

3333
<form method="post"
3434
action="{{ url($crud->route.'/'.$entry->getKey()) }}"
@@ -43,7 +43,7 @@
4343

4444
{{-- load the view from the application if it exists, otherwise load the one in the package --}}
4545
@if(view()->exists('vendor.backpack.crud.form_content'))
46-
@include('vendor.backpack.crud.form_content', ['fields' => $crud->fields(), 'action' => 'edit'])
46+
@include('vendor.backpack.crud.form_content', ['fields' => $crud->fields(), 'action' => 'edit', 'id' => $id])
4747
@else
4848
@include('crud::form_content', ['fields' => $crud->fields(), 'action' => 'edit'])
4949
@endif

src/resources/views/crud/form_content.blade.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515

1616
{{-- Define blade stacks so css and js can be pushed from the fields to these sections. --}}
1717

18-
@section('after_styles')
18+
@push('after_styles')
1919

2020
{{-- CRUD FORM CONTENT - crud_fields_styles stack --}}
2121
@stack('crud_fields_styles')
2222

23-
@endsection
23+
@endpush
2424

25-
@section('after_scripts')
25+
@push('after_scripts')
2626

2727
{{-- CRUD FORM CONTENT - crud_fields_scripts stack --}}
2828
@stack('crud_fields_scripts')
@@ -187,7 +187,10 @@ function preventUnload(event) {
187187
@if ($crud->inlineErrorsEnabled() && session()->get('errors'))
188188
189189
window.errors = {!! json_encode(session()->get('errors')->getBags()) !!};
190+
var submittedFormId = "{{ old('_form_id') }}";
191+
var currentFormId = '{{ $id }}';
190192
193+
if (!submittedFormId || submittedFormId === currentFormId) {
191194
$.each(errors, function(bag, errorMessages){
192195
$.each(errorMessages, function (inputName, messages) {
193196
var normalizedProperty = inputName.split('.').map(function(item, index){
@@ -231,6 +234,7 @@ function preventUnload(event) {
231234
});
232235
});
233236
});
237+
}
234238
@endif
235239
236240
$("a[data-bs-toggle='tab']").click(function(){
@@ -245,4 +249,4 @@ function preventUnload(event) {
245249
</script>
246250

247251
@include('crud::inc.form_fields_script')
248-
@endsection
252+
@endpush

src/resources/views/crud/inc/form_fields_script.blade.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* javascript manipulations, and makes it easy to do custom stuff
77
* too, by exposing the main components (name, wrapper, input).
88
*/
9+
if (typeof CrudField === 'undefined') {
910
class CrudField {
1011
constructor(name) {
1112
this.name = name;
@@ -197,4 +198,5 @@ class CrudField {
197198
// Create all fields from a given name list
198199
fields: names => names.map(window.crud.field),
199200
};
201+
}
200202
</script>

src/resources/views/crud/inc/grouped_errors.blade.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
{{-- Show the errors, if any --}}
22
@if ($crud->groupedErrorsEnabled() && session()->get('errors'))
3+
@php
4+
$submittedFormId = old('_form_id') ?? null;
5+
$currentFormId = $id ?? null;
6+
@endphp
7+
@if (!$submittedFormId || $submittedFormId === $currentFormId)
38
<div class="alert alert-danger">
49
<ul class="list-unstyled">
510
@foreach(session()->get('errors')->getBags() as $bag => $errorMessages)
@@ -11,4 +16,5 @@
1116
@endforeach
1217
</ul>
1318
</div>
19+
@endif
1420
@endif
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
@includeWhen(!empty($widget['wrapper']), backpack_view('widgets.inc.wrapper_start'))
2+
<div class="{{ $widget['class'] ?? 'card' }}">
3+
@if (isset($widget['content']['header']))
4+
<div class="card-header">
5+
<div class="card-title mb-0">{!! $widget['content']['header'] !!}</div>
6+
</div>
7+
@endif
8+
<div class="card-body">
9+
10+
{!! $widget['content']['body'] ?? '' !!}
11+
12+
<div class="card-wrapper form-widget-wrapper">
13+
<x-backpack::data-form :controller="$widget['controller']" />
14+
</div>
15+
16+
</div>
17+
</div>
18+
@includeWhen(!empty($widget['wrapper']), backpack_view('widgets.inc.wrapper_end'))

0 commit comments

Comments
 (0)