New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show tab with empty HTML5 required input on form submit #224

Closed
Toutouwai opened this Issue Aug 26, 2018 · 4 comments

Comments

Projects
None yet
3 participants
@Toutouwai

Toutouwai commented Aug 26, 2018

Short description of the enhancement

It would be cool if PW enhanced its support of HTML5 required inputs. I'm thinking primarily of ProcessPageEdit here but perhaps there could be other applications too.

Currently if there is an empty input with the HTML5 required attribute on a tab that isn't currently active then the Page Edit form cannot be submitted but there is no feedback to the user, and Chrome gives the following error in the console:

An invalid form control with name='field_name' is not focusable.

I know there is a note in the field settings advising that the HTML5 required attribute should only be used on fields that are always visible to the user, but I think there is an opportunity to support required fields on inactive tabs.

My idea is that PW should respond to the "invalid" event for inputs and show the WireTab the invalid field is on, so the notice is visible to the user.

I've been doing some experimenting and this nearly works...

$(function() {
    $(':input[required]').on('invalid', function () {
        var $tab_content = $(this).parents('.Inputfield').last();
        var $tab = $('#PageEditTabs').find('#_' + $tab_content.attr('id'));
        $tab.click();
    });
});

...the only catch being that the top submit button also triggers a click() which prevents a simultaneous WireTab click().

So a workaround is to add a slight delay to the WireTab click(), but show the tab content immediately so that the required field can be focused and the notice displayed:

$(function() {
    $(':input[required]').on('invalid', function () {
        var $tab_content = $(this).parents('.Inputfield').last();
        var $tab = $('#PageEditTabs').find('#_' + $tab_content.attr('id'));
        $tab_content.show();
        setTimeout(function() {
            $tab.click();
        }, 25);
    });
});

Of course if there are multiple empty required fields on multiple tabs then these cannot all be shown simultaneously but the user can work through them on subsequent attempted submits.

Why would the enhancement be useful to users?

The immediate feedback that the browser provides without needing to wait for a server response is arguably a better experience for the user.

More ideas

There could be an option in the field settings to specify a custom notice per field.
https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation#Customized_error_messages

The "required if" JS could be updated to dynamically add/remove the required attribute, to support HTML5 required in "required if" scenarios also.

@Toutouwai

This comment has been minimized.

Show comment
Hide comment
@Toutouwai

Toutouwai Aug 26, 2018

Update to un-collapse a collapsed required field if empty:

$(function() {
    $(':input[required]').on('invalid', function () {
        var $inputfield_ancestors = $(this).parents('.Inputfield');
        var $inputfield_wrap = $inputfield_ancestors.first();
        var $tab_content = $inputfield_ancestors.last();
        var $tab = $('#PageEditTabs').find('#_' + $tab_content.attr('id'));
        $inputfield_wrap.removeClass('InputfieldStateCollapsed');
        $tab_content.show();
        setTimeout(function() {
            $tab.click();
        }, 25);
    });
});

Toutouwai commented Aug 26, 2018

Update to un-collapse a collapsed required field if empty:

$(function() {
    $(':input[required]').on('invalid', function () {
        var $inputfield_ancestors = $(this).parents('.Inputfield');
        var $inputfield_wrap = $inputfield_ancestors.first();
        var $tab_content = $inputfield_ancestors.last();
        var $tab = $('#PageEditTabs').find('#_' + $tab_content.attr('id'));
        $inputfield_wrap.removeClass('InputfieldStateCollapsed');
        $tab_content.show();
        setTimeout(function() {
            $tab.click();
        }, 25);
    });
});
@rolandtoth

This comment has been minimized.

Show comment
Hide comment
@rolandtoth

rolandtoth Sep 8, 2018

Or perhaps just show a (styled?) alert with field and tab name? That would avoid the issue with long tabs where the field is below the fold and scroll would be necessary. Of course scrollIntoView() could help, though sticky headers and such could still cause troubles.

rolandtoth commented Sep 8, 2018

Or perhaps just show a (styled?) alert with field and tab name? That would avoid the issue with long tabs where the field is below the fold and scroll would be necessary. Of course scrollIntoView() could help, though sticky headers and such could still cause troubles.

ryancramerdesign added a commit to processwire/processwire that referenced this issue Sep 11, 2018

Improvements and refactorings to inputfields.js, plus add processwire…
…/processwire-requests#224, and addition of new public API methods: InputfieldFocus($inputfield) which finds, opens and focuses an Inputfield (making it visible) regardless of where it is in the interface; InputfieldOpen($inputfield) which opens a collapsed Inputfield; and InputfieldClose($inputfield) which does the opposite. Thanks to @Toutouwai for the feature request and example code that got this started.
@ryancramerdesign

This comment has been minimized.

Show comment
Hide comment
@ryancramerdesign

ryancramerdesign Sep 11, 2018

Contributor

Thanks @Toutouwai I have added this. I used your suggestion as the starting point and continued from there. Now in addition to tabs, it handles revealing any collapsed parents too (like fieldsets). I put it behind a JS API function InputfieldFocus($inputfield) which finds and reveals the Inputfield wherever it is, opens any collapsed parents or tabs, and then focuses the input within it, when appropriate.

Contributor

ryancramerdesign commented Sep 11, 2018

Thanks @Toutouwai I have added this. I used your suggestion as the starting point and continued from there. Now in addition to tabs, it handles revealing any collapsed parents too (like fieldsets). I put it behind a JS API function InputfieldFocus($inputfield) which finds and reveals the Inputfield wherever it is, opens any collapsed parents or tabs, and then focuses the input within it, when appropriate.

@Toutouwai

This comment has been minimized.

Show comment
Hide comment
@Toutouwai

Toutouwai Sep 15, 2018

Thanks Ryan, just tried it and it's working great!

Toutouwai commented Sep 15, 2018

Thanks Ryan, just tried it and it's working great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment