33 * Copyright (c) 2018 - 2025 Vaadin Ltd.
44 * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
55 */
6+ import { html , render } from 'lit' ;
7+ import { ifDefined } from 'lit/directives/if-defined.js' ;
68import { LoginMixin } from './vaadin-login-mixin.js' ;
79
810function isCheckbox ( field ) {
@@ -15,40 +17,114 @@ function isCheckbox(field) {
1517 */
1618export const LoginFormMixin = ( superClass ) =>
1719 class LoginFormMixin extends LoginMixin ( superClass ) {
18- static get observers ( ) {
19- return [ '_errorChanged(error)' ] ;
20- }
21-
20+ /** @protected */
2221 get _customFields ( ) {
23- return [ ...this . $ . vaadinLoginFormWrapper . children ] . filter ( ( node ) => {
22+ return [ ...this . children ] . filter ( ( node ) => {
2423 return node . getAttribute ( 'slot' ) === 'custom-form-area' && node . hasAttribute ( 'name' ) ;
2524 } ) ;
2625 }
2726
27+ /** @protected */
28+ get _userNameField ( ) {
29+ return this . querySelector ( '#vaadinLoginUsername' ) ;
30+ }
31+
32+ /** @protected */
33+ get _passwordField ( ) {
34+ return this . querySelector ( '#vaadinLoginPassword' ) ;
35+ }
36+
37+ /**
38+ * Override update to render slotted form and buttons
39+ * into light DOM after rendering shadow DOM.
40+ * @protected
41+ */
42+ update ( props ) {
43+ super . update ( props ) ;
44+
45+ this . __renderSlottedForm ( ) ;
46+ }
47+
48+ /** @protected */
49+ updated ( props ) {
50+ super . updated ( props ) ;
51+
52+ if ( props . has ( 'error' ) && this . error && ! this . _preventAutoEnable ) {
53+ this . disabled = false ;
54+ }
55+ }
56+
2857 /** @protected */
2958 async connectedCallback ( ) {
3059 super . connectedCallback ( ) ;
3160
3261 if ( ! this . noAutofocus ) {
3362 // Wait for the form to fully render.
3463 await new Promise ( requestAnimationFrame ) ;
35- this . $ . vaadinLoginUsername . focus ( ) ;
64+ this . _userNameField . focus ( ) ;
3665 }
3766 }
3867
39- /** @private */
40- _errorChanged ( ) {
41- if ( this . error && ! this . _preventAutoEnable ) {
42- this . disabled = false ;
43- }
68+ __renderSlottedForm ( ) {
69+ render (
70+ html `
71+ < form method ="POST " action ="${ ifDefined ( this . action ) } " @formdata ="${ this . _onFormData } " slot ="form ">
72+ < input id ="csrf " type ="hidden " />
73+ < vaadin-text-field
74+ name ="username "
75+ .label ="${ this . __effectiveI18n . form . username } "
76+ .errorMessage ="${ this . __effectiveI18n . errorMessage . username } "
77+ id ="vaadinLoginUsername "
78+ required
79+ @keydown ="${ this . _handleInputKeydown } "
80+ autocapitalize ="none "
81+ autocorrect ="off "
82+ spellcheck ="false "
83+ autocomplete ="username "
84+ manual-validation
85+ >
86+ < input type ="text " slot ="input " @keyup ="${ this . _handleInputKeyup } " />
87+ </ vaadin-text-field >
88+
89+ < vaadin-password-field
90+ name ="password "
91+ .label ="${ this . __effectiveI18n . form . password } "
92+ .errorMessage ="${ this . __effectiveI18n . errorMessage . password } "
93+ id ="vaadinLoginPassword "
94+ required
95+ @keydown ="${ this . _handleInputKeydown } "
96+ spellcheck ="false "
97+ autocomplete ="current-password "
98+ manual-validation
99+ >
100+ < input type ="password " slot ="input " @keyup ="${ this . _handleInputKeyup } " />
101+ </ vaadin-password-field >
102+ </ form >
103+
104+ < vaadin-button slot ="submit " theme ="primary submit " @click ="${ this . submit } " .disabled ="${ this . disabled } ">
105+ ${ this . __effectiveI18n . form . submit }
106+ </ vaadin-button >
107+
108+ < vaadin-button
109+ slot ="forgot-password "
110+ theme ="tertiary small "
111+ @click ="${ this . _onForgotPasswordClick } "
112+ ?hidden ="${ this . noForgotPassword } "
113+ >
114+ ${ this . __effectiveI18n . form . forgotPassword }
115+ </ vaadin-button >
116+ ` ,
117+ this ,
118+ { host : this } ,
119+ ) ;
44120 }
45121
46122 /**
47123 * Submits the form.
48124 */
49125 submit ( ) {
50- const userName = this . $ . vaadinLoginUsername ;
51- const password = this . $ . vaadinLoginPassword ;
126+ const userName = this . _userNameField ;
127+ const password = this . _passwordField ;
52128
53129 // eslint-disable-next-line no-restricted-syntax
54130 userName . validate ( ) ;
@@ -91,8 +167,9 @@ export const LoginFormMixin = (superClass) =>
91167 const csrfMetaName = document . querySelector ( 'meta[name=_csrf_parameter]' ) ;
92168 const csrfMetaValue = document . querySelector ( 'meta[name=_csrf]' ) ;
93169 if ( csrfMetaName && csrfMetaValue ) {
94- this . $ . csrf . name = csrfMetaName . content ;
95- this . $ . csrf . value = csrfMetaValue . content ;
170+ const csrf = this . querySelector ( '#csrf' ) ;
171+ csrf . name = csrfMetaName . content ;
172+ csrf . value = csrfMetaValue . content ;
96173 }
97174 this . querySelector ( 'form' ) . submit ( ) ;
98175 }
@@ -117,8 +194,7 @@ export const LoginFormMixin = (superClass) =>
117194 _handleInputKeydown ( e ) {
118195 if ( e . key === 'Enter' ) {
119196 const { currentTarget : inputActive } = e ;
120- const nextInput =
121- inputActive . id === 'vaadinLoginUsername' ? this . $ . vaadinLoginPassword : this . $ . vaadinLoginUsername ;
197+ const nextInput = inputActive . id === 'vaadinLoginUsername' ? this . _passwordField : this . _userNameField ;
122198 // eslint-disable-next-line no-restricted-syntax
123199 if ( inputActive . validate ( ) ) {
124200 if ( nextInput . checkValidity ( ) ) {
0 commit comments