Understanding Forms rendering

dakur
Member | 493
+
+1
-

I have to admit I am pretty lost in form rendering. There are getControl(), getControlPrototype() and getControlPart() methods for input field but I have no idea why there are all of them, why they are named in such way and what are they for. The same for labels. Also, errors do not have these getters even there is {inputError} macro in Latte as well as {input} and {label} – I would expect something similar to be defined in (Base)Control as well. (yeah I found the macro definition but you know… macro definitions are not for humans 🙂)

Now I want to make custom composite field – a radio list with items now, in three days and other and if other is selected then user can type a date into a date field. getValue() of this composite field always return a DateTime object. But I can not force Forms to use my custom getControl() implementation, because it renders everything into <input [HERE]> – which throws an error because it would render <input <input>...> in my case. Maybe I can use $this->container->setHtml() somehow but not pretty sure.

Also all of these Components, Containers, Controls and other abstractly-named stuff in nette/component-model, nette/application and nette/forms which relations are difficult to imagine for me. As I can't afford spending hours on parsing Forms low-levels from source, I am forced to fiddle it on my own. So I am using framework but can use only half of it. :-)

I would appreciate documenting this stuff to be able to better use it when making custom fields. It could possibly also increase contribution to Nette because more people would understand it.

But I understand it's time-consuming to write docs. So maybe someone could make an (online) workshop or something on how Forms rendering works and what are different parts of it for? Or maybe I missed one?

Thanks for your work though, this should not be critics, I am just an average John Doe programmer who tries to clear things up. :-)

Last edited by dakur (2020-04-03 06:39)

Toanir
Member | 57
+
0
-

Hello there! I'm working on a goofly little application supporting a treasure hunt game. To make things a bit more fun, I created myself an EmojiMatrixControl which works as an substitute to a password field and instead of text password, it takes a combination of symbols. This setup doesn't require any javascript as it uses plain checkboxes and some styling. You can check it's getControl method used for rendering as well as loadHttpData method used for processing of data recieved in submitting HTTP request.

I've taken a shortcut and didn't implement the controlPrototype pattern but typically it is a Nette\Utils\Html instance representing “blank state” outermost element of the control (in my case, the $wrapper = Html::el('div', ['class' => 'pass-matrix']); element). The controlPrototype is usually used when composing a Form to add specific classes and/or adjust other attributes of the element.

You should probably avoid manually setting html of any container and try to stick to your custom control class. Please try to create a Control representing your DateTime selector even if you are unsure how to finish it and post share it here, preferably via link to github or gist.

Toanir
Member | 57
+
0
-

As for the components, controls and containers,,, well… I too struggled at first with the component and control disambiguation. Initially I stuck with toying with controls and as time went on and I was more sure about controls and containers, I began experimenting with components too and it all makes sense since then.

Basically Component is whatever that can be well defined, maybe exactly encapsulated and most likely reused. It can be a form, some kind of widget and our Presenters are special case of Component too. They all together compose a Component Model (I suppose you've seen https://doc.nette.org/…n/components). In most cases a parent component creates a child component via createComponentComponentNameHere method.

Some components can be renderable and then they typically use Control parent class. They are usually rendered in template via macro {control componentNameHere}. The terminology can pose a bit steeper learning curve but I promise it is worth digging through.

I wish you all the patience you need and hope you learn to have fun using Nette. If you have further questions, be sure to hit us up here