Jump to content

How to get $page on Inputfield::render hook?


Juergen
 Share

Recommended Posts

Hello,

I have written a hook to disable an inputfield on certain conditions:

//Disable createevents field if there are no children
$this->pages->addHookBefore('Inputfield::render', function($event) {
    $page = $event->arguments(0);
    $field = $event->object;
    if(in_array($page->template->name, array('event_businessvacations','event_specialbusinesshours','event_dates','event_events'))) {    
      if(count($page->children) == 0){
       if('createevents' === $field->name ){
        $field->attr("disabled" , "disabled");
       }
      }
     } 
});

I am getting always following notice from Tracy:

PHP Notice: Trying to get property of non-object in /home/.sites/24/site1275/web/site/ready.php:310

This is the line where $page is defined.

How can I grab $page in this case correctly or do I have to use another type of Hook?

Link to comment
Share on other sites

Use $e->object->hasPage property

// Inputfield.php
 * @property null|bool|Fieldtype $hasFieldtype The Fieldtype using this Inputfield, or boolean false when known not to have a Fieldtype, or null when not known. #pw-group-other
 * @property null|Field $hasField The Field object associated with this Inputfield, or null when not applicable or not known. #pw-group-other
 * @property null|Page $hasPage The Page object associated with this Inputfield, or null when not applicable or not known. #pw-group-other

 

  • Thanks 1
Link to comment
Share on other sites

Both possible solutions dont work

$page = $event->object->hasPage; 

or

$pages->addHookBefore('Inputfield::render', function($event)

instead of

$this->pages->addHookBefore('Inputfield::render', function($event) 

$page is always empty :(

Link to comment
Share on other sites

27 minutes ago, kongondo said:

$this outside class context shouldn't work as well...

@kongondo
$this
inside any template file will return the TemplateFile object and inside ready.php the ProcessWire object.

@Juergen
If you need to disable fields for certain roles or make them view only take this as a starting point. Put the code in your ready.php
 

foreach ($fields as $field) {
    if ($field->hasFlag(8) && $field->name !== 'title') continue; // skip system fields `Field::flagSystem`
    $field->addFlag(160); // Add flags `Field::flagAccess` = 32 + `Field::flagAccessEditor` = 128

    // Applicable only if the `Field::flagAccess` is set to this field's flags.
    $field->editRoles = array(); // leave empty if you want to give access to superuser only
    $field->viewRoles = array(1026); // assign field view permission to specific roles (IDs)

    // save the field
    $field->save();
}

 

Link to comment
Share on other sites

I have put the code inside the ready.php, but I need to run it only on certain templates and under certain conditions. Therefore I need the page to get the template associated with it.

So I dont want to disable them permanently only if the page has no children. If childrens were created the field should be enabled.

The idea is to make this field (a checkbox field) checked and disabled if there are no children created.

If the user has created at least 1 child page, then this checkbox field will be unchecked and enabled.

The automatic checking works with this Hook after a new page (with no children) is added

//Set create events to true if there are no child pages
$this->pages->addHookAfter('added', function($event) {
    $page = $event->arguments('page');
    $field = $event->arguments('field');
    if(in_array($page->template->name, array('event_businessvacations','event_specialbusinesshours','event_dates','event_events'))) {
     if(count($page->children) == 0){
      $page->setAndSave('createevents', true);
     }
    }
});

To prevent the user to uncheck the checkbox I want to disable it in this case.

Link to comment
Share on other sites

/**
 * check & hide specific checkbox field if page being edited has no children
 */
if ($page->process == 'ProcessPageEdit' && $input->id) {
    $field = $fields->get('createevents');
    $_page = $pages->get($input->id);
    if ($_page->template->fields->hasField('createevents')) {
        if ($page->hasChildren() == false) {
            $field->set('flags',160);
            $field->setRoles('edit',array()); // works for non superuser only
            $_page->setAndSave('createevents', true);
        }
    }
}

 

  • Like 1
Link to comment
Share on other sites

1 hour ago, Juergen said:

I have written a hook to disable an inputfield on certain conditions:


//Disable createevents field if there are no children
$this->pages->addHookBefore('Inputfield::render', function($event) {
    $page = $event->arguments(0);
    $field = $event->object;
    if(in_array($page->template->name, array('event_businessvacations','event_specialbusinesshours','event_dates','event_events'))) {    
      if(count($page->children) == 0){
       if('createevents' === $field->name ){
        $field->attr("disabled" , "disabled");
       }
      }
     } 
});

 

There are a number of problems here I think.

 

$this->pages->addHookBefore('Inputfield::render', function($event) {

You only use $this->pages to add a hook if you are hooking a method of the Pages class. You are hooking a method of the Inputfield class, so you want...

$wire->addHookBefore('Inputfield::render', function($event) {

Also, you don't need to hook every inputfield render. You are only interested in Checkbox inputfields so just hook the render method of that inputfield class.

$wire->addHookBefore('InputfieldCheckbox::render', function($event) {

 

$page = $event->arguments(0);

Inputfield::render() and InputfieldCheckbox::render() take no arguments, so $page is not the first argument and you cannot get $page this way.

 

$field = $event->object;

The event object is an Inputfield object and not a Field object. It doesn't really matter what you name your variables, but to keep things clear in your head it might help to change this to:

$inputfield = $event->object;

 

if('createevents' === $field->name ){

<opinion>Yoda conditions make code less readable and more prone to misinterpretation. The disadvantages outweigh the benefits.</opinion>

 

I would tend to write this hook as:

$wire->addHookBefore('InputfieldCheckbox::render', function(HookEvent $event) {
    if($this->process != 'ProcessPageEdit') return;
    $page = $this->process->getPage();;
    $inputfield = $event->object;
    if(in_array($page->template->name, array('event_businessvacations', 'event_specialbusinesshours', 'event_dates', 'event_events'))) {
        if($inputfield->name === 'createevents' && !count($page->children)) {
            $inputfield->attr('disabled' , 'disabled');
        }
    }
});

Another tip is that when identifying an inputfield by name, it can be better to check the name of the associated field rather than the inputfield. This is because when an inputfield is inside a repeater its name includes a repeater suffix. Checking the associated field name works in all situations so I prefer that.

if($inputfield->hasField == 'createevents' //...

Note also the change to the == comparison operator. Not every inputfield has an associated field, so you couldn't be sure that hasField returns an object with the name property if you did:

$inputfield->hasField->name === 'createevents' //...

 

  • Like 7
Link to comment
Share on other sites

  • 1 year later...
On 9/11/2019 at 2:52 PM, Jonathan Lahijani said:

If the field being hooked is inside of a repeater, how can I get the repeater's page id?

Since this thread was started a hasPage property has been added to Inputfield instances in PW.

Quote
hasPage null Page The Page object associated with this Inputfield, or null when not applicable or not known.

So you can do this:

$wire->addHookBefore('Inputfield::render', function(HookEvent $event) {
	/* @var Inputfield $inputfield */
	$inputfield = $event->object;
	$page = $inputfield->hasPage;
	if($page) {
		// Use $page
		bd($page->name, 'page name');
	}
});

 

  • Like 2
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...