In previous articles, I've shown you how to: create an operation (EmailOperation) with a custom HTML form; use that operation on yo...
In previous articles, I've shown you how to:
But... what about if we want a custom form... to re-use Backpack fields? It's super-useful sometimes to just use select2
, repeatable
, daterange_picker
, etc.
Good news: we can use the power of the 50+ fields Backpack offers. But... how do you do that? It's not that difficult actually... Here's how we can create the same EmailOperation
we've created before, but this time using Backpack fields, not a custom HTML form.
So if we want our admin to send email... what do we need? We need:
a Button for each user, that opens a form. We place it as an action in the list view;
a Form with subject & message fields submitting to an endpoint;
an Endpoint that takes in the form request, validates it and sends the email.
First of all, we need a custom operation, to integrate with Backpack’s routes & user interface.
If you've installed backpack/generators, you can generate an empty operation trait using php artisan backpack:crud-operation Email
Here we will add the two routes in setupEmailRoutes()
and two methods as follows:
getEmailForm()
to show the form.postEmailForm()
to process submit request.// app/Http/Controllers/Admin/Operations/EmailOperation.php
protected function setupEmailRoutes($segment, $routeName, $controller){
- Route::get($segment . '/email', [
+ Route::get($segment . '/{id}/email', [
+ 'as' => $routeName . '.email',
- 'uses' => $controller.'@email',
+ 'uses' => $controller . '@getEmailForm',
+ 'operation' => 'email',
+ ]);
+ Route::post($segment . '/email/send/{id}', [
+ 'as' => $routeName . '.email-send',
+ 'uses' => $controller . '@postEmailForm',
+ 'operation' => 'email',
+ ]);
}
+
+ public function getEmailForm() {}
+
+ public function postEmailForm() {}
In this example, I'm using EmailOperation
inside UserCrudController
. If you're the one that created UserCrudController
, it should be as simple as:
use \App\Http\Controllers\Admin\Operations\EmailOperation;
If not, and you're using PermissionManager's UserCrudController
, click here to see how to take control of its UserCrudController.
We need a button to display inside the list view, so let's create it:
If you've installed backpack/generators, you can generate an empty operation trait using:
php artisan backpack:button email
// resources/views/vendor/backpack/crud/buttons/email.blade.php
@if ($crud->hasAccess('email'))
<a href="{{ url($crud->route.'/'.$entry->getKey().'/email') }}" class="btn btn-sm btn-link text-capitalize"><i class="la la-envelope"></i> email</a>
@endif
Then let's use it inside the EmailOperation.php
we've created in the first step:
protected function setupEmailDefaults(){
$this->crud->allowAccess('email');
$this->crud->operation('email', function () {
$this->crud->loadDefaultOperationSettingsFromConfig();
});
$this->crud->operation('list', function () {
// $this->crud->addButton('top', 'email', 'view', 'crud::buttons.email');
- // $this->crud->addButton('line', 'email', 'view', 'crud::buttons.email');
+ $this->crud->addButton('line', 'email', 'view', 'crud::buttons.email');
});
}
Let's copy the Create View from Backpack:
php artisan backpack:publish crud/create
Then rename the created file from create.blade.php
to email_form.blade.php
, more specifically it'd be:
/resources/views/vendor/backpack/crud/email_form.blade.php
The only change needed in this file is Form's POST Method URL as follows:
-<form method="post" action="{{ url($crud->route) }}">
+<form method="post" action="{{ url($crud->route.'/email/send/'.$entry->getKey()) }}">
Attention! Backpack crud views load some configurations from the config file, so let's duplicate the create
config file and use it in our own operation. Just copy-paste and rename config/backpack/operations/create.php
to config/backpack/operations/email.php
Now we'll define getEmailForm()
to show the email form:
public function getEmailForm(){
$this->crud->hasAccessOrFail('email');
$this->crud->setHeading('Send Email');
$this->crud->setSubHeading('Sending email to ' . backpack_user()->name);
$this->data['crud'] = $this->crud;
$this->data['entry'] = $this->crud->getCurrentEntry();
$this->data['saveAction'] = $this->crud->getSaveAction();
$this->data['title'] = "Send email to " . backpack_user()->name;
return view('crud::email_form', $this->data);
}
At this point, we have our email form... but no fields... so let's add Backpack fields to the form and the save action button inside a new setupEmailOperation()
(similar to what we normally do for the Create operation):
protected function setupEmailOperation(){
$this->crud->addField([
'name' => 'from',
'type' => 'text',
'value' => config('mail.from.address'),
'wrapper' => [
'class' => 'form-group col-md-4',
],
'validationRules' => 'required|email'
]);
$this->crud->addField([
'name' => 'to',
'type' => 'text',
'value' => $this->crud->getCurrentEntry()->email,
'attributes' => [
'readonly' => 'readonly',
'disabled' => 'disabled',
],
'wrapper' => [
'class' => 'form-group col-md-4',
],
]);
$this->crud->addField([
'name' => 'reply_to',
'type' => 'text',
'value' => backpack_user()->email,
'wrapper' => [
'class' => 'form-group col-md-4',
],
'validationRules' => 'nullable|email'
]);
$this->crud->addField([
'name' => 'subject',
'type' => 'text',
'validationRules' => 'required|min:5',
]);
$this->crud->addField([
'name' => 'message',
'type' => 'textarea',
'validationRules' => 'required|min:5',
]);
$this->crud->addSaveAction([
'name' => 'send_email',
'redirect' => function ($crud, $request, $itemId) {
return $crud->route;
},
'button_text' => 'Send Email',
]);
}
Now let's define postEmailForm()
to validate and process form submission:
use Illuminate\Support\Facades\Mail;
use Prologue\Alerts\Facades\Alert;
use Exception;
public function postEmailForm(){
$this->crud->hasAccessOrFail('email');
$request = $this->crud->validateRequest();
$entry = $this->crud->getCurrentEntry();
try {
// send the actual email
Mail::raw($request['message'], function ($message) use ($entry, $request) {
$message->from($request->from);
$message->replyTo($request->reply_to);
$message->to($entry->email, $entry->name);
$message->subject($request['subject']);
});
Alert::success('Mail Sent')->flash();
return redirect(url($this->crud->route));
} catch (Exception $e) {
// show a bubble with the error message
Alert::error("Error, " . $e->getMessage())->flash();
return redirect()->back()->withInput();
}
}
That's it, here's what we're getting from the above:
You can find the final code of this example here in this gist.
We learnt about the flexibility of Backpack and created a custom email action... that can use ANY Backpack field. We can use the same principles to define an SMS operation, for example. I hope it was helpful 😀
Let us know what you think in the comments below. Or tell us about something cool you've have built, at [email protected]
Subscribe to our "Article Digest". We'll send you a list of the new articles, every week, month or quarter - your choice.
What do you think about this?
Wondering what our community has been up to?