Jump to content

Removing "Add new" from PageTable field


Recommended Posts

Hi everyone,

after successfully solving the mystery "PageTable", I stumbled upon another one: removing the "add new" button from PageTable (in the template) via hooks.

So, I read about hooks. I never implemented one myself, but tried using the "init" PHP file from the default site, but that didn't work out too well. So again I am a bit stuck in the process. :(

Basically, I check if an array is empty. If it is, the PageTable field on my template shouldn't display the "add new" button. That's about it.

Since PageTable is fairly new, I didn't find too much info about it. Maybe someone of you is able to help me?

Thanks a lot!

Link to comment
Share on other sites

EDIT: Ignore this idea completely - soma's solution hooking into InputfieldButton::render is obviously a much better idea :)

I don't have time right now to put a working solution together, but you'll want to hook into InputfieldPageTable::render and do an $event->replace = true and then scan the content and strip out the add new button. You could do that with a regex, eg:

function strip_selected_tags_by_id_or_class($array_of_id_or_class, $text) 
   $name = implode('|', $array_of_id_or_class); 
   $regex = '#<(\w+)\s[^>]*(class|id)\s*=\s*[\'"](' . $name . 
   return(preg_replace($regex, '', $text)); 

or perhaps more efficiently with domdocument's removeChild() - eg: http://stackoverflow.com/questions/12903483/remove-a-domnode-with-a-certain-class-in-php

Something like this:

class RemoveAddButton extends WireData implements Module {

    public static function getModuleInfo() {
        return array(
            'title' => 'Conditionally Remove Page Table Add Button',
            'version' => 1,
            'singular' => true,
            'autoload' => true

    public function init() {
        $this->addHookAfter('InputfieldPageTable::render', $this, 'removeButton');

    public function removeButton(HookEvent $event) {
        $event->replace = true;
            $event->return = regex or removechild here to remove button from original $event->return;

Hope that gets you going. Otherwise, I'll put something working together for you tomorrow.

Edited by adrian
Obviously not a good approach to things :)
  • Like 4
Link to comment
Share on other sites

I've to add a few things here. In your other thread we where talking about denying the page creating and your idea now is hiding the button upfront. Both ways to solve your problem should be not that different to implement, as both need just hooks to work. 

Now, after writing the post, came this to my mind: 
InputfieldPageTable::render is only called on, big surprise, page render. So in your usecase, this wouldn't be great, because the limit of pages in your pagetable has to work even if the user doesn't leave the page. So I still think that my suggestion of using Pages::add would be more useful, even if it's a little bit less userfriendly, because the add button will throw an error, instead of simply disappearing.

An addition to adrians post: You put your hook in the init.php in the template folder? If so, it can't work because this file is only called if your browsing the frontend. You need your hook to work in the backend. While you can use hooks in template files, we don't change the core admin template files. So the best way to get your hook into the backend is via a small module, like the one adrian posted. This example code with the docs about hooks and modules here on processwire.com should get you at least somewhere.
What's missing in the code of adrian, is a condition, when to remove the "add" button. I would limit the check for players / positions to the right template or the right field in the hook and only then do the checkup.

  • Like 3
Link to comment
Share on other sites

Here's an example module that removes "Add New" button(s) on InputfieldPageTable on a condition (here if there's 2 ore more entries).

Hook before InputfieldPageTable::render, then add hook after InputfieldButton::render. Since InputfieldButton is used by PageTable, we just use that hook to empty the returned markup for the button. Then remove that button hook after the InputfieldPageTable rendered.


  • Like 9
Link to comment
Share on other sites

Okay guys I am truly overwhelmed by your support. I think this is VERY rare nowadays.

That really encourages me to support PW even more by buying some Pro modules soon. It's really, really good to have a community like this! :lol:

@adrian: Thank you for you effort. After reading your code it gave me a more deeper understanding on where to put the hooks!

@LostKobrakai: Your dedication is stunning. ;) And you're right: the "init" PHP is only executed front-end wise. Thank you for opening my eyes!

Basically, you're right. Adding this hook globally to all pages might seem too much, but Soma does a little check before doing anything:

if($table->name !== "mypagetable") return;

I think the performance hit (if any) is still bearable.

@Soma: Hero Member really suits you. I just copied your source from Git, installed the module and it worked out of the box! :rolleyes:

I cannot mark two posts as "solved", so the "solved" goes also to yours, adrian!

Just a short follow up to working with classes: since I'm outside the normal scope of the "$pages" object, I have to use the global (ugh) "wire('pages')" inside the class instead, am I right?

  • Like 3
Link to comment
Share on other sites

Obviously a much better approach from Soma! so I definitely don't deserve a "Solved" on this one :)

Of course my original code snippet didn't exclude other fields, but I was thinking something along the lines of checking the name of the field before proceeding - just didn't get that far when posting in a rush yesterday :)

  • Like 1
Link to comment
Share on other sites

  • 1 year later...

Hello @ all,

I read Somas solution how to remove the add button and I have tried to adapt the code for another condition. Soma uses the number of rows as his condition but I want to use the value of a field instead, but I can get it to work.

In my case I want to use a fieldtype option (select) in the page template to remove the add button or not. If option "1" is selected the button should be removed - if option "2" is selected the button should be still there.

Here is what I have tried:

   public function renderPageTable(HookEvent $event){
         // get the table field
        $table = $event->object;
        $page = $event->arguments[0];
        // make sure this is our field
        if($table->name !== "singleeventtable") return;
        // rendered by InputfieldButton::render
        if($page->eventkindchooser == "1") {
            $this->buttonHook = $this->addHookAfter("InputfieldButton::render", null, function(HookEvent $event){
                // overwrite/remove button markup
                $event->return = '';

Eventkindchooser is the name of the option fieldtype.

Can anyone point me into the right direction?

Link to comment
Share on other sites

  • 1 year later...
On 8/31/2014 at 3:44 AM, Soma said:

Here's an example module that removes "Add New" button(s) on InputfieldPageTable on a condition (here if there's 2 ore more entries).


Thank you so much for this. It's a fantastic example which I'm using as of yesterday. I particularly appreciate you posting clean code as I find reading code the best way for me to learn how things work.


Do you possibly have any examples of a hook in which I could manipulate more of the admin interface? I'd like to do a couple things:

1. Remove the "settings tab" in the iframe that pops up when editing a PageTable entry. Maybe it's possible to do so with roles and permissions or a technique similar to removing the button.

2. Change the function of the "Add New" button completely - don't create/load the iframe and just create a new PageTable entry programmatically.

If there are hooks to point me at I can figure them out. I've spent time with Captain Hook and but am a bit overwhelmed with the sheer number as well as the fact that I don't know much about how the admin interface is constructed.


Link to comment
Share on other sites

58 minutes ago, bmacnaughton said:

Remove the "settings tab" in the iframe that pops up when editing a PageTable entry. Maybe it's possible to do so with roles and permissions or a technique similar to removing the button.

I found this in the meantime - thanks for this post as well.

I got the this working by turning on $config->advanced = true; in config.php which allows hiding the settings tab on a per-template basis! Nice.

It seems that the code in the thread turns off the general ProcessWire menus as well:

Before and after shots attached.

Screenshot from 2017-04-23 08-57-52.png

Screenshot from 2017-04-23 08-59-39.png

I'm working on 2) now.


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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By daniel_puehringer
      Hi community,

      I am using the "PageTable" Module (also called "ProFields: Page Table") and the built in "Language" Module (also called "Languages Support").

      With the help of PageTable I was able to create several content elements which should usually be displayed in German(default language) and English.

      However some Content Elements should only be shown in German and NOT in English.

      Well sounds easy, right? Not so fast. I really love this CMS, but I have not found a solution for this problem yet.
      As you can see in the screenshots attached I tried to uncheck the "active" Checkbox for the english language to completely hide the content element for english users.

      However no matter what I do the german text shows on the english page.
      If I leave the "content-should-not-be-shown-in-english"(see Screenshot Number 2) blank and save the page, the page will inherit the german page url "content-element-with-simple-text-which-should-only-be-shown-in-german".

      My question therefore is:
      How can I hide a specific content-element for only one language?

      I´m using the latest processwire & module versions.

      The code which I use to render the content elements looks like this:
      //Info: contentelements is a field of type "ProFields: Page Table" <?php foreach ($page->contentelements as $element): echo($element->render()); endforeach; ?> filename: basic-page.php

      I would really appreciate your help since I haven´t found a solution after reading through quite a lot of forum posts.

      All the best,

    • By picarica
      So hello i am trying to get a .png file from file field and put it automatically to image field, why png image is in the file field is because i already have a hook that extracts .zip and uploads all content into file field, but i just realizes i cant use size() function on image in file field so i am tryin got reupload it to images field
      i already have something like  this in ready.php
      $word = ".png"; foreach($page->subor_hry as $file) { if(strpos($file, $word) !== false){ $page->images_thumb = $file->url; } } by my logic it should work but it dosnt i get error ProcessPageEdit: Unable to read: /site-hry/assets/files/1027/flash_fishy_screenshot.png
      when i remove url from $file->url i just get ProcessPageEdit: Item added to ProcessWire\Pageimages is not an allowed type
      so what am i doing wrong? is there some other way to do this ?
      also can i have all this in
      $this->addHookAfter('Pages::saveReady', function(HookEvent $event) { whats the correct function to have it apply on all pages ?
    • By rooofl
      Hi! I am trying to create a hook that takes the value of a form file field, and add it to an image gallery of an existing page.
      $forms->addHookBefore('FormBuilderProcessor::processInputDone', function($e) { $form = $e->arguments(0); if($form->name == 'new-inuse') { // related_font is a page selector $font = $form->getChildByName('related_font'); // getting the page name $fontName = $font->attr('value')->name; // finds the page from its name $fontPage = wire('pages')->find("name=$fontName"); // in_use_image is a file upload field $image = $form->getChildByName('in_use_image'); // trying to add the image to the existing image gallery in_use field $fontPage->in_use->add('$image'); // error here $fontPage->save(); } }); This outputs the following error: `Call to a member function add() on null`. Any idea what’s wrong with my code?
    • By picarica
      so what i am trying to do is that i uploded some files into file field, and then i want hook to get MD5sum and other stuff from .xml and put it into text field into it coresponding pages, pages like this are gonna be many, for each one i want it to output it into its fields
    • By Paul Greinke
      Hi there. I wrote a custom module for one of my projects. In fact I maybe want to use my module in other projects too. In order to be variable and customizable  I need to implement some custom hooks into my module. So I can afterwards hook into the my functions in order to modify them to match the needs of the new project.
      I tried simply defining functions with the '__' prefix. But that did not work. I'm imagining something like the following:
      <?php class MyClass { public function ___someFunction() { // Do something } } // ready.php $this->addHookBefore('MyClass::someFunction', function($event) { // some customization }); Is there a way to accomplish that? 
  • Create New...