Jump to content

Recommended Posts

Posted

Hi PW Community,

for a RockForms nette Form I need a custom Markup for the RadioList Control.

addRadioList outputs the control per default as

<label><Input type=radio /> Text</label>

what I want to achieve:

<Input type=radio /><label>Text</label>

I can add classes and Separator Markup. But how can I inject a custom Markup?

Any ideas?

Posted

Hey @Jochen Fritsch there are several ways to achieve this, but may I ask WHY you want to do that? There are reasons for it having this markup. AI Quote:

Quote

Accessibility Issues
- Screen Reader Compatibility: The <label><input> structure is the standard HTML pattern that screen readers expect. When a label wraps an input, it creates an implicit association that's universally supported.
- Click Target Size: With <label><input>, clicking anywhere on the label text activates the radio button. This provides a much larger click target, which is especially important for mobile users and those with motor difficulties.
- WCAG Compliance: The wrapped label pattern is explicitly mentioned in WCAG guidelines as the preferred method for form controls.

Browser Compatibility
- Older Browsers: Some older browsers and assistive technologies may not properly handle the <input><label> pattern.
- Form Validation: Browser-native form validation features work more reliably with the standard pattern.

Posted

Hi @bernhard

this has styling reasons. The accessibility argument is correct. I have to give the radio:checked + text element a special styling. So, I need a wrapper for the Input + text caption. Is there a way to wrap the caption?

Posted

Ok I still don't understand but here you go:

    $f = $form->addRadioList('demo', 'Demo', [
      'foo' => 'Foo Option',
      'bar' => 'Bar Option',
    ]);
    $form->rockforms()->hookField(function (HtmlPageCrawler $field) {
      // $field->outerHtml() is the whole field pair (label + input + errors)

      // find all defined <label> elements
      $field->filter('label')->each(function (HtmlPageCrawler $label) {
        // $label->html() is something like this:
        // <label><input type="radio" name="demo" value="foo">Foo Option</label>
        
        // get <input> element
        $input = $label->filter('input')->first();
        
        // no input found (this is the field pair label)
        if (!$input->count()) return;
        
        // get input html
        $inputHtml = $input->outerHtml();
        
        // remove input and get remaining inner html
        $input->remove();
        $rest = $label->html();
        $label->replaceWith("$rest - whatever - $inputHtml");
      });
    }, $f);

Unfortunately Nette is quite complicated when it comes to modifying markup. You could write a custom renderer, but that's also not so easy. That's why I have built the hookField helper that uses RockFrontend's dom tools to do whatever markup manipulation you need.

For simpler use cases (eg displaying two fields side by side) check out the addMarkup() helper:

$form->addMarkup("<div class='uk-flex'>{field1} {field2}</div>");

Since you need to change the inner markup structure of the field it is a bit more complex in your scenario 🙂 

Posted

Hi @bernhard

thanks for your quick reply and your hookField hint. I´ve tried to use this helper in my buildForm() function. But unfortunately I get this error:

Call to undefined function RockForms\rockforms()

Are there missing dependencies? Have I forgotten something?

Thanks a lot!

Posted

You need to have the proper use statement at the top or use the full name with the namespace:

F3X3XDG.png

RockForms have "namespace RockForms", so if you use "rockforms()" in this file it will look for "\RockForms\rockforms()" which does not exist. So you either use "\ProcessWire\rockforms()" or you add the use statement.

If that's not done correctly my ide shows me the problem:

R35J3o5.png

PS: You can also use $form->rockforms()

Posted
19 hours ago, fliwire said:

https://chatgpt.com/share/687cd89c-e074-8005-aa0a-e8c850457edf

you can use new css :has selector for styling not needed "input + label"

label:has(input[checked="checked"]) {
    text-decoration: line-through;
}

 

Hi @fliwire

thanks for this CSS "trick" but that won`t work in my case, because I have to add an additional pseudo-element ::before to the label. So I need a wrapper for the text element.
But good hint 👍

Thank you!

Posted

Hi @bernhard

thanks for the Support 🙂
One other question...
I would like to set a field Default ->setDafaults() by a POST Parameter.
When the $form is called with this POST Param the default should by set by this.

How can I pass a POST Param to the buildForm() function or use it in there?
Currently it is empty, when I pass it from the page and when I use it in the buildForm() function I get an Error.

Call to a member function post() on null

Sorry, I hope, this no "dumb" question. I`m on my way 😉

Posted

I'm not sure I understand. buildForm is called when the form is rendered, which would be a GET request.

So this is how you could set defaults based on get params:

    $form->addText('demo', 'Demo')
      ->setDefaultValue(wire()->input->get('demo'));

Again you need to import wire() correctly or use $form->wire->input

Lq8g7oo.png

  • Like 1
  • Jochen Fritsch changed the title to [solved] RockForms nette RadioList Control Renderer

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...