Closed mrizkihidayat66 closed 2 months ago
Hi @mrizkihidayat66, I think your problem must be solved using JavaScript.
First is publish the views to custom, like this:
php artisan vendor:publish --tag=wizard-views-bs5
Then you can add some JavaScript code below resources/views/vendor/wizard/base.blade.php
:
</div>
<script>
// do something...
</script>
@endsection
This has some examples:
How can I intercept the "Next" button when it's pressed?
<script>
document.querySelector('form').addEventListener('submit', function (e) {
if (have_something_should_prevent_next_button) {
e.preventDefault();
}
});
</script>
In a specific scenario, how can I force skip next step with "Next" button or programmatically?
The skip for step you can see Skip step, then remove the click event of "Skip" button.
Now you must add the id skip
to "Skip" button and next
to "Next" button, then add click event using JS:
<script>
// call the "Next" button programmatically
document.getElementById('skip').click();
// call the "Next" button programmatically
document.getElementById('next').click();
</script>
How can I disable the "Back" button in certain situations?
Add the disabled
for button html or using blade @if
:
<button type="button" class="btn btn-primary" disabled>
@lang('wizard::generic.back')
</button>
@if ($condition)
<button type="button" class="btn btn-primary">
@lang('wizard::generic.back')
</button>
@endif
I can only give you these tips, but as long as you have a blade view, you can use PHP and JavaScript to do what you want to do.
This is an interesting approach, but I was expecting it to use steps and a controller like before. However, I'll give this approach a try. Thank you.
If you want to use steps and a controller, this has some examples:
How can I intercept the "Next" button when it's pressed?
Use the beforeWizardStepSave()
hook in the WizardController
, it will called before step validation and any processing:
use Illuminate\Http\Request;
class UserWizardController extends Controller
{
protected function beforeWizardStepSave(Request $request)
{
// do somthing
dd('clicked Next button');
// or return redirect response
return back();
}
}
In a specific scenario, how can I force skip next step with "Next" button or programmatically?
use Illuminate\Http\Request;
class UserWizardController extends Controller
{
protected function beforeWizardStepSave(Request $request)
{
// first you need cache the current status
if ($this->wizard()->option('cache')) {
$step = $this->getWizardStep($request, $request->route('step'));
$step->cacheProgress($request);
}
// force redirect to next
return $this->redirectTo();
// or redirect to other step, pass the step slug
return $this->redirectTo('email');
}
}
How can I disable the "Back" button in certain situations?
Add to all steps:
class EmailStep extends Step
{
protected $back = true;
public function showBackButton(bool $show = null)
{
if ($show !== null) {
$this->back = $show;
}
return $this->back;
}
}
Add into view:
base.blade.php
@if ($stepRepo->hasPrev() && $step->showBackButton())
<button type="button" class="btn btn-primary" ...>
@lang('wizard::generic.back')
</button>
@endif
Called the methods:
$step->showBackButton(); // get back button show status
$step->showBackButton(false); // set back button is hidden
Hi, mate. When I try to implement beforeWizardStepSave
in the controller, the validation rules are not being executed
Hi, mate. When I try to implement
beforeWizardStepSave
in the controller, the validation rules are not being executed
Because the beforeWizardStepSave()
is before the validation, if you do not intercept and is to do when validated, you should use the wizardStepFormValidated()
hook.
class LicenseWizardController extends Controller
{
protected function beforeBackWizardStep(Request $request)
{
/** @var mixed $step */
$step = $this->wizard()->stepRepo()->current();
if (method_exists($step, 'beforeBack')) {
$step->beforeBack();
}
return true;
}
protected function wizardStepSaved(Request $request)
{
/** @var mixed $step */
$step = $this->wizard()->stepRepo()->current();
if (method_exists($step, 'beforeNext') && $request->query('_trigger') !== 'back') {
$step->beforeNext();
}
}
...
class CustomerStep extends Step
{
public function beforeNext() {
\Illuminate\Support\Facades\Log::info('a');
}
...
class ProductStep extends Step
{
public function beforeBack() {
try {
$cart = app(\App\Services\CartService::class);
$cart->clearCart();
}
catch (\Exception $e) {
Log::error('Error: ' . $e->getMessage());
}
}
public function beforeNext() {
\Illuminate\Support\Facades\Log::info('b');
if (!$this->validation()) {
//
}
}
public function validation()
{
try {
$cart = app(\App\Services\CartService::class);
$customer_detail = optional($this->find('customer'))->data() ?? [];
$cartItems = $cart->getCart();
function checkOrderType($customer_detail) {
$type = 'new';
if (($customer_detail['status'] ?? '') === 'no' || ($customer_detail['order'] ?? '') === 'renew') {
$type = 'renew';
}
return $type;
}
switch (checkOrderType($customer_detail)) {
case 'renew':
{
}
break;
default:
{
$allValid = collect($cartItems)->every(function ($item) {
return $item['type'] === 'new' &&
$item['item_id'] === null &&
$item['duration'] <= 3;
});
if (!$allValid) {
throw new \Exception('Cart validation failed for new order type. Ensure all items meet the criteria.');
}
return true;
}
break;
}
}
catch (\Exception $e) {
Log::error('Error: ' . $e->getMessage());
return false;
}
}
...
This kind of interception for the back/next buttons works well, but I can't get it to influence the intercepted workflow. For example, in the following scenario, I want to prevent advancing to the next step.
if (!$this->validation()) {
//
}
Oh, I understand your intention 😅, you want add some custom validation, could use ValidationException
to throw the custom validation message:
use Illuminate\Validation\ValidationException;
class ProductStep extends Step
{
public function saveData(Request $request, $data = null, $model = null)
{
// saving the request data...
// the 'your_field' is the input field name to show the validation message
throw ValidationException::withMessages([
'your_field' => 'The error after saved data.',
]);
}
public function beforeBack() {
try {
$cart = app(\App\Services\CartService::class);
$cart->clearCart();
} catch (\Exception $e) {
// the 'your_field' is the input field name to show the validation message
throw ValidationException::withMessages([
'your_field' => $e->getMessage(),
]);
}
}
}
Then set the cache
to false
for the WizardController
:
class LicenseWizardController extends Controller
{
/**
* The wizard options.
*
* @var array
*/
protected $wizardOptions = [
'cache' => false,
];
protected function beforeBackWizardStep(Request $request)
{
/** @var mixed $step */
$step = $this->wizard()->stepRepo()->current();
if (method_exists($step, 'beforeBack')) {
$step->beforeBack();
}
return true;
}
}
And I have changed the behavior for beforeBackWizardStep
, please upgrade the package to ^4.1.0
:
composer update ycs77/laravel-wizard:^4.1
I know you are unfamiliar with this package, but I need to give you a little reminder. If you open an issue to ask a question, you need to provide the context and more information for the issue, and the package author or contributor then knows your intention and will give back the best answer, it saves time.
For example in this conversation, the last code I know your intention is "throw the custom validation error or message", but it is not contained in the original question. I read the "How can I intercept the Next button when it's pressed?" I got the "How to intercept the button", so my first answer is to give you the JavaScript code.
I give you a method, I think this method not only applies to this package. If you want to ask a question about the software or package, you can provide some information:
And if you provide the example code with markdown, you could add syntax highlighting to increase readability.
I think it can speed up to resolution of the issue, the above is provided for your reference.
If you have any problem welcome to open a new issue, happy coding!
Noted. I'm unfamiliar with this library and need more flexibility from it. Could you review my private project and provide your advice based on my unique case? If you can, I'll send you an invitation.
Could you review my private project and provide your advice based on my unique case?
The support of the private project is not in the range with this package, so if you want my support, which contains the code review and advice, please add a month of $30 to my sponsor, you could add just one month and then cancel it then get only one month support.
My Patreon link is: https://www.patreon.com/ycs77
Or you can keep the current method to continue to open the issues.
Done, please check your patreon message~
Thanks to your sponsors❤️
Hi there,
I apologize for the frequent questions, but I'm truly grateful for your amazing library—it's been incredibly helpful. However, due to my limited skills and understanding, along with the unique requirements of my project, I'm finding it challenging to apply the library effectively.
Could you kindly assist me with the following?
Thank you so much for your help!