nette/forms
Nette Forms is a PHP library for building, rendering, and validating HTML forms with minimal code. It offers CSRF protection, file uploads, flexible controls, and a rich set of validation rules through a clean, secure, and extensible API.
The headline of 3.3 is CSRF protection that the browser handles for you – no token, no cookie, no server-side state, and it holds even against XSS. On top of that, the confusing {formContext} / {formContainer} pair collapses into a single {form scope}, you can finally nest forms with {form detached}, and a round of housekeeping clears out long-deprecated APIs. Please test and report anything that breaks for you.
Sec-Fetch-Site header instead of the old SameSite cookie. The previous mechanism trusted submissions from any subdomain of the same site; the new one demands an exact origin match (scheme + host + port).setValues() / setDefaults() now expect iterable|stdClass.RadioList / CheckboxList: getControlPart() and getLabelPart() throw on an invalid item key instead of silently returning a nonsensical result.DataClassGenerator, LatteRenderer, getValues(true) (use getValues('array')), and the $default parameter of getOption() (use the ?? operator), negative validation rules{form scope name} – one tag to replace the easily-confused {formContext} and {formContainer}. It pushes the form onto the stack without emitting <form>, resolving the name relatively to an active form when there is one, otherwise from the top level.{form detached name} – nest forms at last. HTML forbids nested <form> tags, so detached emits an empty <form></form> up front and links every control back to it via the HTML5 form="..." attribute, no matter where they sit in the DOM.addSubmit() accepts an $onSubmit callback – attach a click handler right when you create the button, without a separate ->onClick[] =.{form} arguments – write {form name, attr=val} instead of {form name attr=val}, freeing keywords like scope/detached next to the name.The headline of 3.3 is CSRF protection that the browser handles for you – no token, no cookie, no server-side state, and it holds even against XSS. On top of that, the confusing {formContext} / {formContainer} pair collapses into a single {form scope}, you can finally nest forms with {form detached}, and a round of housekeeping clears out long-deprecated APIs. Please test and report anything that breaks for you.
Sec-Fetch-Site header instead of the old SameSite cookie. The previous mechanism trusted submissions from any subdomain of the same site; the new one demands an exact origin match (scheme + host + port).setValues() / setDefaults() now expect iterable|stdClass.RadioList / CheckboxList: getControlPart() and getLabelPart() throw on an invalid item key instead of silently returning a nonsensical result.DataClassGenerator, LatteRenderer, getValues(true) (use getValues('array')), and the $default parameter of getOption() (use the ?? operator), negative validation rules{form scope name} – one tag to replace the easily-confused {formContext} and {formContainer}. It pushes the form onto the stack without emitting <form>, resolving the name relatively to an active form when there is one, otherwise from the top level.{form detached name} – nest forms at last. HTML forbids nested <form> tags, so detached emits an empty <form></form> up front and links every control back to it via the HTML5 form="..." attribute, no matter where they sit in the DOM.addSubmit() accepts an $onSubmit callback – attach a click handler right when you create the button, without a separate ->onClick[] =.{form} arguments – write {form name, attr=val} instead of {form name attr=val}, freeing keywords like scope/detached next to the name.A maintenance-focused release that tightens type safety across the whole codebase, modernizes the JavaScript test stack, and turns static analysis into a non-negotiable part of the build. No API changes – just a more solid foundation under the hood.
Container, BaseControl, Validator, Rules, Form and friends, so PHPStan (and your IDE) see the real shape of thingsallowCrossOrigin() for clarityRadioList::getControl() return empty element when has no itemsContainer::addEmail(): added $maxLength=255 #303getValue() instead of loadHttpData()__call() nette/utils#315Container::getValue() supports conversion to enums [Close #337]setNullable()Helpers::getSupportedTypes() returns array #332isNullable()<option> is hidden/disabled when is requiredHidden on Windows:
Disabled on Apple:
SubmitButton::setValidationScope() accepts stringsContainer::getUntrustedValues() has default value<label> for CheckboxList/RadioList itemsaddDate(), addTime() & addDateTime(), addColor()getCacheKey() to force refresh cacheaddFloat()Container::getValues() respects validation scope #287<dialog> by defaultgetUnsafeValues() renamed to getUntrustedValues()Form::initialize() sets 'secure' flag nette/http#217ControlGroup::getOption() parameter $default is silently deprecatedForm::addProtection() fixed error "Argument 3 must be of the type string or null, int given"fireRenderEvents()addFilter()getValue() #277<button> #273Form::addGroup() loose type (#269)<dialog> in Opera & mobile Chromium because it loses focus after alert() #275showModal() methodForm::getValues() fixed when in validation scope is containercompatible with PHP 8.0
toggle()toggle() even during initialization (possible BC break)hasOwnProperty() checkvalidateControl() #252For the details you can have a look at the diff.
For the details you can have a look at the diff.
validateNumeric() accepts unsigned integer #246getIterator() moves BLANK before FILLED #233getToggleStates() synced with netteForms.js toggleControltoggleControl(), synced with validateControl()validate() $emptyOptional is always false in BLANK conditionFor the details you can have a look at the diff.
setOptionAttribute()validateInteger() returns false when integer is too bigdata-nette-rules #243getLabel() removed return type void #241For the details you can have a look at the diff.
setNullable() and addFilter() #171addRule() checks upload_max_filesize limitremoveRule()setHtmlAttribute()formatMessage() label is translated using form translator (#237)For the details you can have a look at the diff.
formatMessage() Fixed using label placeholder in validation rule with Html label (#235)__toString() is allowed since PHP 7.4For the details you can have a look at the diff.
How can I help you explore Laravel packages today?