7

I am trying to bind backAfterSaveStatus value to hidden input and for some reason then form is submited backAfterSave value is null. After that I go back and submit form again - backAfterSave value is 1. Where is the problem? I tried same thing without prevent and submit() but it's not working still. Also I had dumped div with x-text and code makes hidden input 1 before form submit. What I am doing wrong?

<form action="<...>" method="post">
    <div x-data="{
        backAfterSaveStatus: '',
        backAfterSave () {
            this.backAfterSaveStatus = '1';
            document.querySelector('form.withBackAfterSave').submit();
        }
    }">
        <input name="backAfterSave" :value="backAfterSaveStatus">
        <div>
            <span>
                <button x-on:click.prevent="backAfterSave()" type="submit">
                    Save & back
                </button>
            </span>
            <span>
                <button type="submit">
                    Save
                </button>
            </span>
        </div>
    </div>
</form>

I want same result as below:

let buttonBackAfterSave = document.getElementById('button-back-after-save');

if (buttonBackAfterSave) {
    buttonBackAfterSave.addEventListener('click',  () => document.getElementById('input-back-after-save').value = 1);
}
IGP
  • 14,160
  • 4
  • 26
  • 43
keizah7
  • 649
  • 4
  • 18
  • Don't you need to reset the value of `backAfterSaveStatus = 0` after the `submit()` call in the `backAfterSave()` method – Donkarnash Nov 22 '20 at 13:09
  • I tried it also, but main problem is that first time after form submit value is null. – keizah7 Nov 22 '20 at 13:14
  • @keizah Is this issue specific to alpine/php or can it be solved using JS as well? So to resume, whe the form is submitted, and only after submission, you want to be able to click the button save and back and display 1 inside the input field, correct? – rags2riches-prog Dec 19 '20 at 17:26
  • 1
    I reproduced the issue and solved it using the [`$nextTick` magic property](https://github.com/alpinejs/alpine/#nexttick) – IGP Dec 19 '20 at 18:36

3 Answers3

1

The problem is the form being submitted "too fast" (the backAfterSaveStatus value isn't done binding to the input). Use $nextTick so Alpine waits until the value is properly changed.

<form method="post" class="withBackAfterSave">
    @csrf
    <div x-data="{
        backAfterSaveStatus: '',
        backAfterSave () {
            this.backAfterSaveStatus = '1';
            this.$nextTick(() => { document.querySelector('form.withBackAfterSave').submit() });
        }
    }">
        <input name="backAfterSave" x-bind:value="backAfterSaveStatus">
        <div>
            <span>
                <button x-on:click.prevent="backAfterSave()" type="submit">
                    Save & back
                </button>
            </span>
            <span>
                <button type="submit">
                    Save
                </button>
            </span>
        </div>
    </div>
</form>
IGP
  • 14,160
  • 4
  • 26
  • 43
0

Thank you! I don't use x-ref because these buttons are in separate layouts file, so I can't move it outside x-data range. My final code:

<div class="pt-5">
    <div class="flex justify-end" x-data="{
        backAfterSave: 0
    }">
        <input type="hidden" name="backAfterSave" :value="backAfterSave">
        <button type="button"
                class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
            {{ __('Cancel') }}
        </button>
        <button type="submit"
                @click.prevent="backAfterSave=1; $nextTick(() => {
                    document.querySelector('form.with-back-after-save').submit()
                })"
                class="ml-3 inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
            {{ __('Save & back') }}
        </button>
        <button type="submit"
                class="ml-3 inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-teal-600 hover:bg-teal-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-teal-500">
            {{ __('Save') }}
        </button>
    </div>
</div>
keizah7
  • 649
  • 4
  • 18
0

Just released that I could use simple button with custom name and given value.. No javascript was needed :)

<button type="submit" name="back-after-submit" value="1">Save</button>
keizah7
  • 649
  • 4
  • 18