Skip to content

Commit 227bb95

Browse files
authored
Merge pull request #3 from webfactor/1.0
1.0
2 parents 09f7029 + 9856932 commit 227bb95

File tree

5 files changed

+259
-4
lines changed

5 files changed

+259
-4
lines changed

README.md

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,130 @@ composer require webfactor/laravel-backpack-instant-fields
2020

2121
## Usage
2222

23+
### EntityCrudController
24+
25+
In the EntityCrudController that is supposed to PROVIDE instant creation (not in the CrudController where you want to USE instant fields!) you have to embed the `CanBeCreatedOnTheFly` trait from this package.
26+
27+
```php
28+
<?php
29+
30+
use Webfactor\Laravel\Backpack\InstantFields\CanBeCreatedOnTheFly;
31+
32+
class EntityCrudController extends CrudController
33+
{
34+
use CanBeCreatedOnTheFly;
35+
36+
//
37+
}
38+
```
39+
40+
This trait provides all needed route entry points methods and ajax response methods.
41+
42+
### Routes
43+
44+
in your routes file you have to add three additional routes for you `CRUD::resource`. For clarity we recommend to use the `with()` helper:
45+
46+
```php
47+
<?php
48+
49+
CRUD::resource('entity', 'EntityCrudController')->with(function () {
50+
Route::get('entity/ajax/create', 'EntityCrudController@ajaxCreate');
51+
Route::get('entity/ajax', 'EntityCrudController@ajaxIndex');
52+
Route::post('entity/ajax', 'EntityCrudController@ajaxStore');
53+
});
54+
```
55+
56+
### Available Fields
57+
58+
There are two field types available in this package which allow you an instant creation of related models (1-n and n-m). They are modified versions of the equivalent field types that already exist in Laravel Backpack:
59+
60+
- [select2_from_ajax](https://laravel-backpack.readme.io/docs/crud-fields#section-select2_from_ajax)
61+
- [select2_from_ajax_multiple](https://laravel-backpack.readme.io/docs/crud-fields#section-select2_from_ajax_multiple)
62+
63+
To use instant creation capability of these field types you have to add the `on-the-fly` key
64+
65+
```
66+
'on_the_fly' => [
67+
'create_view' => backpack_url('entity/ajax/create'),
68+
]
69+
```
70+
71+
If you use Laravel Backpack Crud >=3.4.11 you don't have to publish the provided fields, you can use them directly from the package by using the `view_namespace` key.
72+
2373
Example:
2474

75+
```
76+
[
77+
'name' => 'entity_id',
78+
'type' => 'select2_from_ajax',
79+
'label' => 'Entity',
80+
'view_namespace' => 'webfactor::fields',
81+
'model' => Entity::class,
82+
'entity' => 'entity',
83+
'attribute' => 'name',
84+
'data_source' => backpack_url('entity/ajax'),
85+
'placeholder' => 'Choose',
86+
'minimum_input_length' => 0,
87+
'on_the_fly' => [
88+
'create_view' => backpack_url('entity/ajax/create'),
89+
],
90+
],
91+
```
92+
93+
## Multiple instant fields
94+
95+
If you want to use more than one instant field in a CrudController you have to define separate names for each so that JQuery is able to trigger the modals in the right way.
96+
97+
### EntityCrudController
98+
99+
In the EntityCrudController that provides instant creation you have to set the `$ajaxEntity` property by using the setter in the `setup()`-method:
100+
25101
```php
26102
<?php
27103

28-
// to be added
104+
use Webfactor\Laravel\Backpack\InstantFields\CanBeCreatedOnTheFly;
105+
106+
class EntityCrudController extends CrudController
107+
{
108+
use CanBeCreatedOnTheFly;
109+
110+
public function setup()
111+
{
112+
// other Backpack options
113+
$this->setAjaxEntity('name_of_entity');
114+
115+
// fields/columns definitions
116+
}
117+
}
118+
```
119+
120+
### Field definition
121+
122+
In the field definition you have to add `entity` to the `on-the-fly` key and give it the exact same name as in the EntityCrudController above.
123+
124+
```
125+
'on_the_fly' => [
126+
'create_view' => backpack_url('entity/ajax/create'),
127+
'entity' => 'name_of_entity',
128+
]
129+
```
130+
131+
## Customization
132+
133+
### Search behavior
134+
135+
If you need a different search behavior just overwrite the `ajaxIndex()` method in your `EntityCrudController` and write your own search logic.
136+
137+
### Request validation
138+
139+
You can also use Request Validation! Just copy the `ajaxStore()` method to your `EntityCrudController` and replace `Request` by your desired request (usually just `StoreRequest`).
140+
141+
### Fields
142+
143+
Publish the fields in your project and modify functionality
144+
145+
```
146+
php artisan vendor:publish --tag=instantfields
29147
```
30148

31149
## Change log
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<!-- select2 from ajax multiple -->
2+
@php
3+
$connected_entity = new $field['model'];
4+
$connected_entity_key_name = $connected_entity->getKeyName();
5+
$old_value = old($field['name']) ? old($field['name']) : (isset($field['value']) ? $field['value'] : (isset($field['default']) ? $field['default'] : false ));
6+
@endphp
7+
8+
<div @include('crud::inc.field_wrapper_attributes') >
9+
<label>{!! $field['label'] !!}</label>
10+
@include('crud::inc.field_translatable_icon')
11+
<select
12+
name="{{ $field['name'] }}[]"
13+
style="width: 100%"
14+
id="select2_ajax_multiple_{{ $field['name'] }}"
15+
@include('crud::inc.field_attributes', ['default_class' => 'form-control'])
16+
multiple>
17+
18+
@if ($old_value)
19+
@foreach ($old_value as $item)
20+
@if (!is_object($item))
21+
@php
22+
$item = $connected_entity->find($item);
23+
@endphp
24+
@endif
25+
<option value="{{ $item->getKey() }}" selected>
26+
{{ $item->{$field['attribute']} }}
27+
</option>
28+
@endforeach
29+
@endif
30+
</select>
31+
32+
@if (isset($field['on_the_fly']))
33+
<button href="{{ $field['on_the_fly']['create_view'] }}"
34+
type="button"
35+
class="btn btn-primary"
36+
data-toggle="modal"
37+
data-target="#{{ $field['on_the_fly']['entity'] ?? 'ajax_entity' }}_modal">
38+
{{ trans('backpack::crud.add') }}
39+
</button>
40+
<div class="modal fade"
41+
id="{{ $field['on_the_fly']['entity'] ?? 'ajax_entity' }}_modal"
42+
tabindex="-1"
43+
role="dialog"
44+
aria-labelledby="{{ $field['on_the_fly']['entity'] ?? 'ajax_entity' }}_modal"
45+
aria-hidden="true">
46+
<div class="modal-dialog" role="document">
47+
<div class="modal-content"></div>
48+
</div>
49+
</div>
50+
@endif
51+
52+
{{-- HINT --}}
53+
@if (isset($field['hint']))
54+
<p class="help-block">{!! $field['hint'] !!}</p>
55+
@endif
56+
</div>
57+
58+
59+
{{-- ########################################## --}}
60+
{{-- Extra CSS and JS for this particular field --}}
61+
{{-- If a field type is shown multiple times on a form, the CSS and JS will only be loaded once --}}
62+
@if ($crud->checkIfFieldIsFirstOfItsType($field, $fields))
63+
64+
{{-- FIELD CSS - will be loaded in the after_styles section --}}
65+
@push('crud_fields_styles')
66+
<!-- include select2 css-->
67+
<link href="{{ asset('vendor/adminlte/bower_components/select2/dist/css/select2.min.css') }}" rel="stylesheet" type="text/css" />
68+
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2-bootstrap-theme/0.1.0-beta.10/select2-bootstrap.min.css" rel="stylesheet" type="text/css" />
69+
@endpush
70+
71+
{{-- FIELD JS - will be loaded in the after_scripts section --}}
72+
@push('crud_fields_scripts')
73+
<!-- include select2 js-->
74+
<script src="{{ asset('vendor/adminlte/bower_components/select2/dist/js/select2.min.js') }}"></script>
75+
@endpush
76+
77+
@endif
78+
79+
<!-- include field specific select2 js-->
80+
@push('crud_fields_scripts')
81+
<script>
82+
jQuery(document).ready(function($) {
83+
// trigger select2 for each untriggered select2 box
84+
$("#select2_ajax_multiple_{{ $field['name'] }}").each(function (i, obj) {
85+
if (!$(obj).hasClass("select2-hidden-accessible"))
86+
{
87+
$(obj).select2({
88+
theme: 'bootstrap',
89+
multiple: true,
90+
placeholder: "{{ $field['placeholder'] }}",
91+
minimumInputLength: "{{ $field['minimum_input_length'] }}",
92+
ajax: {
93+
url: "{{ $field['data_source'] }}",
94+
dataType: 'json',
95+
quietMillis: 250,
96+
data: function (params) {
97+
return {
98+
q: params.term, // search term
99+
searchkey: "{{ $field['attribute'] }}", // search key in database
100+
page: params.page
101+
};
102+
},
103+
processResults: function (data, params) {
104+
params.page = params.page || 1;
105+
106+
return {
107+
results: $.map(data.data, function (item) {
108+
return {
109+
text: item["{{$field['attribute']}}"],
110+
id: item["{{ $connected_entity_key_name }}"]
111+
}
112+
}),
113+
more: data.current_page < data.last_page
114+
};
115+
},
116+
cache: true
117+
},
118+
});
119+
}
120+
});
121+
});
122+
</script>
123+
@endpush
124+
{{-- End of Extra CSS and JS --}}
125+
{{-- ########################################## --}}

resources/views/modal/modal_layout.blade.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
@stack('crud_fields_styles')
2-
{!! Form::open(['id' => 'create_'.$entity, 'files'=>$crud->hasUploadFields('create')]) !!}
2+
<form method="post" id="{{ 'create_'.$entity }}" accept-charset="UTF-8">
3+
{{--'files'=>$crud->hasUploadFields('create')])--}}
4+
{{ csrf_field() }}
35
<div class="modal-header">
46
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
57
<span aria-hidden="true">&times;</span>
@@ -13,5 +15,5 @@
1315
<div class="modal-footer">
1416
@yield('footer')
1517
</div>
16-
{!! Form::close() !!}
18+
</form>
1719
@stack('crud_fields_scripts')

src/InstantFieldsServiceProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function boot()
2020
$this->loadViewsFrom(realpath(__DIR__ . '/../resources/views'), 'webfactor');
2121

2222
// publish fields
23-
$this->publishes([__DIR__ . '/../resources/views/fields' => resource_path('views/vendor/backpack/crud/fields')], 'fields');
23+
$this->publishes([__DIR__ . '/../resources/views/fields' => resource_path('views/vendor/backpack/crud/fields')], 'instantfields');
2424
}
2525

2626
/**

src/Traits/CanBeCreatedOnTheFly.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ public function getAjaxEntity()
1818
return $this->ajaxEntity ?? 'ajax_entity';
1919
}
2020

21+
/**
22+
* Sets $ajaxEntity property to use if more than one on-the-fly field is used
23+
*
24+
* @return void
25+
*/
26+
public function setAjaxEntity(string $entity)
27+
{
28+
$this->ajaxEntity = $entity;
29+
}
30+
2131
/**
2232
* Provides the search algorithm for the select2 field. Overwrite it in
2333
* the EntityCrudController if you need some special functionalities

0 commit comments

Comments
 (0)