Jump to content

Replace Inputfield with another type using Inputfield::render hook


Marc
 Share

Recommended Posts

I have a form (outside of the admin) that shows a text field. I want to replace this field with a select field during rendering. The problem is, when I name the replacement field the same as the original, the page stops working. But I'm thinking if I use another name for my replacement field, its value won't be saved to the original field. Here's the hook I'm using in ready.php:

wire()->addHookAfter('Inputfield::render', function($event) {
    if (wire('page')->template != "account") return;

    $inputfield = $event->object;

    if ($inputfield->attr('name') == "profile_pad_countrycode") {
        $replacement = $this->modules->get('InputfieldSelect');
        $replacement->label = 'Land code';
        $replacement->attr('name', 'profile_pad_countrycode'); // This is a problem, the form crashes when using this name.
        $replacement->attr('class', 'uk-select');
        $optionsArray = ['test'];
        $replacement->addOptions($optionsArray);
        $event->return = $replacement->render();
    }
}); 

Can this way of replacing an inputfield ever work? Or should I abandon this idea?

Link to comment
Share on other sites

What's the idea behind it? I don't think that's possible, and certainly not when you're using two completely different types of input fields... perhaps text/textarea might work, but I think it's just a dangerous / adventurous idea...

Link to comment
Share on other sites

17 hours ago, dragan said:

What's the idea behind it? I don't think that's possible, and certainly not when you're using two completely different types of input fields... perhaps text/textarea might work, but I think it's just a dangerous / adventurous idea...

The original text field that I want to replace belongs to a third party module. Rather than changing the field properties of that module, I thought I'd tailor that particular field to my needs with a hook.

I agree this might be a bit dangerous and perhaps I'll end up just changing the module, but it's a fun experiment nonetheless.

 

14 hours ago, Martijn Geerts said:

// Could you test this???
wire()->addHookAfter('Field::getInputfield', function (HookEvent $event) {
	$event->return->inputfield = 'InputfieldSelect';
});

 

I gave this a try. It doesn't appear to have any effect. I should use this in addition to my own hook, right? Is this hook supposed to prepare PW for the change in field type?

 

I did some more testing and even when I try to replace the text field with a new text field (so same field type), it only works as long as the name of the replacement field is not the same as the original (but then you can't save new values using the new field to the old field). When a form gets rendered and it has the replacement field with the same name as the original field, the server hangs and I'll get this fatal error:

Fatal error: Allowed memory size of 268435456 bytes exhausted

So at this point I'll rephrase my question: can I replace a field with a new field of the same type and the same name using a hook? Once I get that working, I'll see if I can use a replacement field of another type.

Link to comment
Share on other sites

1 minute ago, Marc said:

When a form gets rendered and it has the replacement field with the same name as the original field, the server hangs and I'll get this fatal error:

This is an infinite loop you're causing. You hook after the render of a field named a specific name and in the hook you render another field of the same name, which again triggers your hook to replace and so on. You'd either need to find a hook, which won't be triggered again by what you're doing inside the hook execution (like @Martijn Geerts tried) or you need to find a way to differenciate the first call to your hook from the ones triggered by your code within the hook.

  • Like 2
Link to comment
Share on other sites

16 minutes ago, LostKobrakai said:

This is an infinite loop you're causing. You hook after the render of a field named a specific name and in the hook you render another field of the same name, which again triggers your hook to replace and so on. You'd either need to find a hook, which won't be triggered again by what you're doing inside the hook execution (like @Martijn Geerts tried) or you need to find a way to differenciate the first call to your hook from the ones triggered by your code within the hook.

Thank you for helping me understand this. Now I managed to get it working! I give my replacement field an exta attribute called 'replaced' and the hook is only allowed to do its job if the field does not have that extra attribute. Like this:

wire()->addHookAfter('Inputfield::render', function($event) {
    if (wire('page')->template != "account") return;

    $inputfield = $event->object;

    if ($inputfield->attr('name') == "profile_pad_countrycode" && $inputfield->attr('replaced') != "yes") {
        $replacement = $this->modules->get('InputfieldSelect');
        $replacement->label = 'Land code';
        $replacement->attr('name', 'profile_pad_countrycode');
        $replacement->attr('class', 'uk-select');
        $replacement->attr('replaced', 'yes'); // This is essential to prevent a loop. Check for this value when the hook starts.
        $optionsArray = ['test'];
        $replacement->addOptions($optionsArray);
        $event->return = $replacement->render();
    }
}); 
Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

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