1- import { Controller } from '@hotwired/stimulus' ;
2- import Backend , { type BackendInterface } from './Backend/Backend' ;
3- import Component , { proxifyComponent } from './Component' ;
4- import { StimulusElementDriver } from './Component/ElementDriver' ;
1+ import { Controller } from '@hotwired/stimulus' ;
2+ import Backend , { type BackendInterface } from './Backend/Backend' ;
3+ import Component , { proxifyComponent } from './Component' ;
4+ import { StimulusElementDriver } from './Component/ElementDriver' ;
55import ChildComponentPlugin from './Component/plugins/ChildComponentPlugin' ;
66import LazyPlugin from './Component/plugins/LazyPlugin' ;
77import LoadingPlugin from './Component/plugins/LoadingPlugin' ;
88import PageUnloadingPlugin from './Component/plugins/PageUnloadingPlugin' ;
9- import type { PluginInterface } from './Component/plugins/PluginInterface' ;
9+ import type { PluginInterface } from './Component/plugins/PluginInterface' ;
1010import PollingPlugin from './Component/plugins/PollingPlugin' ;
1111import QueryStringPlugin from './Component/plugins/QueryStringPlugin' ;
1212import SetValueOntoModelFieldsPlugin from './Component/plugins/SetValueOntoModelFieldsPlugin' ;
1313import ValidatedFieldsPlugin from './Component/plugins/ValidatedFieldsPlugin' ;
14- import { type DirectiveModifier , parseDirectives } from './Directive/directives_parser' ;
14+ import { type DirectiveModifier , parseDirectives } from './Directive/directives_parser' ;
1515import getModelBinding from './Directive/get_model_binding' ;
16- import { elementBelongsToThisComponent , getModelDirectiveFromElement , getValueFromElement } from './dom_utils' ;
16+ import { elementBelongsToThisComponent , getModelDirectiveFromElement , getValueFromElement } from './dom_utils' ;
1717import getElementAsTagText from './Util/getElementAsTagText' ;
1818
19- export { Component } ;
20- export { getComponent } from './ComponentRegistry' ;
19+ export { Component } ;
20+ export { getComponent } from './ComponentRegistry' ;
2121
2222export interface LiveEvent extends CustomEvent {
2323 detail : {
@@ -30,19 +30,20 @@ export interface LiveController {
3030 element : HTMLElement ;
3131 component : Component ;
3232}
33+
3334export default class LiveControllerDefault extends Controller < HTMLElement > implements LiveController {
3435 static values = {
3536 name : String ,
3637 url : String ,
37- props : { type : Object , default : { } } ,
38- propsUpdatedFromParent : { type : Object , default : { } } ,
39- listeners : { type : Array , default : [ ] } ,
40- eventsToEmit : { type : Array , default : [ ] } ,
41- eventsToDispatch : { type : Array , default : [ ] } ,
42- debounce : { type : Number , default : 150 } ,
43- fingerprint : { type : String , default : '' } ,
44- requestMethod : { type : String , default : 'post' } ,
45- queryMapping : { type : Object , default : { } } ,
38+ props : { type : Object , default : { } } ,
39+ propsUpdatedFromParent : { type : Object , default : { } } ,
40+ listeners : { type : Array , default : [ ] } ,
41+ eventsToEmit : { type : Array , default : [ ] } ,
42+ eventsToDispatch : { type : Array , default : [ ] } ,
43+ debounce : { type : Number , default : 150 } ,
44+ fingerprint : { type : String , default : '' } ,
45+ requestMethod : { type : String , default : 'post' } ,
46+ queryMapping : { type : Object , default : { } } ,
4647 } ;
4748
4849 declare readonly nameValue : string ;
@@ -71,8 +72,8 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
7172 pendingActionTriggerModelElement : HTMLElement | null = null ;
7273
7374 private elementEventListeners : Array < { event : string ; callback : ( event : any ) => void } > = [
74- { event : 'input' , callback : ( event ) => this . handleInputEvent ( event ) } ,
75- { event : 'change' , callback : ( event ) => this . handleChangeEvent ( event ) } ,
75+ { event : 'input' , callback : ( event ) => this . handleInputEvent ( event ) } ,
76+ { event : 'change' , callback : ( event ) => this . handleChangeEvent ( event ) } ,
7677 ] ;
7778 private pendingFiles : { [ key : string ] : HTMLInputElement } = { } ;
7879
@@ -127,7 +128,7 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
127128 }
128129 const rawAction = params . action ;
129130 // all other params are considered action arguments
130- const actionArgs = { ...params } ;
131+ const actionArgs = { ...params } ;
131132 delete actionArgs . action ;
132133
133134 // data-live-action-param="debounce(1000)|save"
@@ -159,7 +160,8 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
159160 directive . modifiers . forEach ( ( modifier ) => {
160161 if ( validModifiers . has ( modifier . name ) ) {
161162 // variable is entirely to make ts happy
162- const callable = validModifiers . get ( modifier . name ) ?? ( ( ) => { } ) ;
163+ const callable = validModifiers . get ( modifier . name ) ?? ( ( ) => {
164+ } ) ;
163165 callable ( modifier ) ;
164166
165167 return ;
@@ -195,19 +197,19 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
195197 }
196198
197199 emit ( event : any ) {
198- this . getEmitDirectives ( event ) . forEach ( ( { name, data, nameMatch } ) => {
200+ this . getEmitDirectives ( event ) . forEach ( ( { name, data, nameMatch} ) => {
199201 this . component . emit ( name , data , nameMatch ) ;
200202 } ) ;
201203 }
202204
203205 emitUp ( event : any ) {
204- this . getEmitDirectives ( event ) . forEach ( ( { name, data, nameMatch } ) => {
206+ this . getEmitDirectives ( event ) . forEach ( ( { name, data, nameMatch} ) => {
205207 this . component . emitUp ( name , data , nameMatch ) ;
206208 } ) ;
207209 }
208210
209211 emitSelf ( event : any ) {
210- this . getEmitDirectives ( event ) . forEach ( ( { name, data } ) => {
212+ this . getEmitDirectives ( event ) . forEach ( ( { name, data} ) => {
211213 this . component . emitSelf ( name , data ) ;
212214 } ) ;
213215 }
@@ -243,7 +245,7 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
243245 }
244246 const eventInfo = params . event ;
245247 // all other params are considered event arguments
246- const eventArgs = { ...params } ;
248+ const eventArgs = { ...params } ;
247249 delete eventArgs . event ;
248250
249251 // data-event="name(product_list)|some_event"
@@ -315,7 +317,7 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
315317 attributes : true ,
316318 } ) ;
317319
318- this . elementEventListeners . forEach ( ( { event, callback } ) => {
320+ this . elementEventListeners . forEach ( ( { event, callback} ) => {
319321 this . component . element . addEventListener ( event , callback ) ;
320322 } ) ;
321323
@@ -324,7 +326,7 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
324326
325327 private disconnectComponent ( ) {
326328 this . component . disconnect ( ) ;
327- this . elementEventListeners . forEach ( ( { event, callback } ) => {
329+ this . elementEventListeners . forEach ( ( { event, callback} ) => {
328330 this . component . element . removeEventListener ( event , callback ) ;
329331 } ) ;
330332 this . dispatchEvent ( 'disconnect' ) ;
@@ -429,14 +431,35 @@ export default class LiveControllerDefault extends Controller<HTMLElement> imple
429431
430432 const finalValue = getValueFromElement ( element , this . component . valueStore ) ;
431433
434+ if (
435+ ( element instanceof HTMLInputElement && [ 'text' , 'email' , 'password' , 'search' , 'tel' , 'url' ] . includes ( element . type ) ) ||
436+ element instanceof HTMLTextAreaElement
437+ ) {
438+ if ( modelBinding . minLength !== null && typeof finalValue === "string" && finalValue . length < modelBinding . minLength ) {
439+ return ;
440+ }
441+ if ( modelBinding . maxLength !== null && typeof finalValue === "string" && finalValue . length > modelBinding . maxLength ) {
442+ return ;
443+ }
444+ }
445+
446+ if ( element instanceof HTMLInputElement && element . type === 'number' ) {
447+ if ( modelBinding . minValue !== null && Number ( finalValue ) < modelBinding . minValue ) {
448+ return ;
449+ }
450+ if ( modelBinding . maxValue !== null && Number ( finalValue ) > modelBinding . maxValue ) {
451+ return ;
452+ }
453+ }
454+
432455 this . component . set ( modelBinding . modelName , finalValue , modelBinding . shouldRender , modelBinding . debounce ) ;
433456 }
434457
435458 private dispatchEvent ( name : string , detail : any = { } , canBubble = true , cancelable = false ) {
436459 detail . controller = this ;
437460 detail . component = this . proxiedComponent ;
438461
439- this . dispatch ( name , { detail, prefix : 'live' , cancelable, bubbles : canBubble } ) ;
462+ this . dispatch ( name , { detail, prefix : 'live' , cancelable, bubbles : canBubble } ) ;
440463 }
441464
442465 private onMutations ( mutations : MutationRecord [ ] ) : void {
0 commit comments