Jump to content

Adding a custom tab on page edit screen


novalex
 Share

Recommended Posts

Hi,

New to PW, please forgive my ignorance if this has been answered before, I have scoured the docs and forums but couldn't find anything.

I'm trying to add a custom tab to the Page Edit screen (or process), which will contain fields for a page hero. Ideally, I would have a "Hero" tab before "Content", which would contain fields for images, text, a CTA button, etc. What I have so far is this:

class HeroTab extends WireData implements Module {

	public static function getModuleInfo() {
		return array(
			'title'    => 'Page Hero',
			'version'  => 1,
			'summary'  => 'Header fields for pages.',
			'singular' => true,
			'autoload' => true,
		);
	}

	public function ready() {
		if(wire('page')->process != 'ProcessPageEdit') return;

		$this->addHookAfter('ProcessPageEdit::buildForm', $this, 'addTab');
	}

	public function addTab(HookEvent $event) {
		$form = $event->return;

		// create the tab
		$hero = new InputfieldWrapper();
		$hero->attr('id+name', $this->className() . 'hero');
		$hero->attr('title', $this->_('Hero'));

		// Images
		$fimages = $this->modules->get("InputfieldImage");
		$fimages->attr('id+name', 'hero_images');
		$fimages->label = $this->_('Images');
		$fimages->extensions = 'gif jpg jpeg png svg';
		$hero->append($fimages);

		// Text
		$ftext = $this->modules->get("InputfieldCKEditor");
		$ftext->attr('id+name', 'hero_text');
		$ftext->label = $this->_('Text');
		$hero->append($ftext);

		$form->prepend($hero);
	}
}

This adds the tab and the fields, but after the "View" tab. However, the bigger problem is that the fields do not save. When I click Save, the page refreshes, with the "Saved Page" notice, but the fields are empty.

I got inspiration from https://github.com/adrianbj/ProcessRedirectIds/blob/master/ProcessRedirectIds.module, but I think it is for the older 2.x version because it originally used $form->append which put the bottom save button between the tabs and tab content.

Any help would be appreciated, I am thoroughly lost and the documentation doesn't give any examples for what I'm trying to do.

Cheers

Screenshot from 2017-05-08 18:21:34.jpeg

Link to comment
Share on other sites

Can't you just make a regular fieldset tab and put them in there, i have sometimes 2-3 content tabs, and there is no reason to make a module.

also on that example posted, the solution provided is only for outputting markup, like some instructions, or like a training video etc. AFAIK you cannot add a tab to page edit and expect those fields to automagically save to the database b/c the fields need to exist in the database to save to.

  • Like 3
Link to comment
Share on other sites

1 minute ago, Macrura said:

Can't you just make a regular fieldset tab and put them in there, i have sometimes 2-3 content tabs, and there is no reason to make a module.

I tried that as well, but these fields need to appear on every page and there's no way to set a fieldset as global, and I don't want them appearing on the fields list either, as I will eventually have many of these custom fields and it will be a mess.

Link to comment
Share on other sites

7 hours ago, novalex said:

I tried that as well, but these fields need to appear on every page and there's no way to set a fieldset as global, and I don't want them appearing on the fields list either, as I will eventually have many of these custom fields and it will be a mess.

All fields in PW are custom fields. And you can't save content to a page without an actual field added to the page's template to hold that content (in your module you are only dealing with inputfields which themselves do not save their content to the DB).

If you like you can add tags to your fields to create groups of fields within the fields list and keep things tidy. As @Macrura said, currently the only way to add a group of fields to a template in the form of a single unit is to create a repeater with those fields and limit it to a single repeater item. Or if you prefer, a PageTable or Profields Table in conjunction with Limit PageTable or Limit Table.

Another approach that I sometimes take (if the project is well planned out in advance) is first create a template with the fields/fieldsets that will be used on all templates, and then I duplicate that template as the starting point for each additional template.

  • Like 4
Link to comment
Share on other sites

Thanks for all the help guys, appreciated. I ended up just creating repeater fields, nested as needed, and it works well enough. Coming from WordPress with ACF or CMB2, I'm surprised how flexible the PW system is and how many options it offers for the fields. I just wish the documentation was a little more comprehensive and offered some examples as well, sort of like the WordPress codex, since I'm having a hard time understanding/following the source code.

I look forward to working with PW some more, I'm sure I'll get the hang of it soon and then it's bye-bye WordPress :)

  • Like 4
Link to comment
Share on other sites

hi novalex!

great that you found a way :) just take care if you have a more complex setup and need some advanced selectors the repeater setup COULD be a problem (or a little harder). if you have 2 regular fields forename and surname a selector would be:

$pages->find('forename=john, surname=doe');

if you have a repeater setup, it would be:

$pages->find('yourgroup.forename=john, yourgroup.surname=doe');

as long as it is simple like this it will work, but i can remember that it can lead to problems but don't remember exactly... just keep in mind that it could be easier to have "duplicate" fields and simple selectors than the other way round ;)

  • Like 1
Link to comment
Share on other sites

Yep, already came across this "issue", where I have to use something like "$page->home_tabs->home_tabs_content" in my template.

I'm not sure if I'm doing this right, I'm used to ACF where field IDs inside repeaters couldn't collide with other fields, so I could do "$home_tabs['content']", but since in PW each field has to have a unique ID, my selectors for nested fields are getting pretty long and hard to read because of the repetition. Any suggestions for that? I can't simplify too much, the site I'm working on now has some complex sections which require heavy repeater use.

Link to comment
Share on other sites

6 hours ago, novalex said:

Yep, already came across this "issue", where I have to use something like "$page->home_tabs->home_tabs_content" in my template.

You can avoid some repetition and shorten the way you get field content in your templates like this:

// Get the repeater item (the item is a page)
$r_item = $page->repeater_field->first();

// Get field content from the item
echo $r_item->foo;
echo $r_item->bar;
echo $r_item->baz;

 

  • Like 3
Link to comment
Share on other sites

Quote

I can't simplify too much, the site I'm working on now has some complex sections which require heavy repeater use.

you would not imagine how often i have thought that myself and then i found out how to do it the processwire-way and it just seemed too simple with something like a 3-liner ;)

"heavy use" of repeater sounds like you could maybe improve/change how you structured your content. in PW thats a very important part of your work. if you structure your project/data well, most of the time you end up with very simple and clean selector-calls like

$pages->find('template=product');
// or
$page->children('category=car');

of course that's just wild guesses, but if you want to share your setup i'm sure you'll get valuable feedback from lots of knowledable guys (and girls) here :)

  • Like 3
Link to comment
Share on other sites

@Robin S There's still repetition because the repeater field properties are also prefixed with the pertinent section ID, such as "home_tabs" to avoid field ID collision. Perhaps I could make a wrapper function to grab fields from a repeater, something like "get_section_field('content', 'home_tabs')", do you think it's a good idea? It seems easier to read to me.

@bernhard Agree on all points! Trouble is, this is a website for a client, the design is already approved and I cannot restructure it. I could have fields for each section, which would simplify things, but the client must be able to edit, add and remove sections as needed, hence the heavy use of repeaters.

I came across another issue, and I have no idea what the problem is. I need a few admin pages to keep various site options such as API keys, common content displayed across pages, etc. I have created two templates, set their icon, and added pages under the admin page tree using these templates. However, in the menu only the parent page appears, and its icon is the default sheet of paper, not the cog I have selected. Screenshot of the page tree and admin menu attached. Any idea what I'm doing wrong?

Cheers, and thanks for all the help so far!

Alex

Screenshot from 2017-05-17 11:47:36.png

Link to comment
Share on other sites

2 hours ago, novalex said:

There's still repetition because the repeater field properties are also prefixed with the pertinent section ID, such as "home_tabs" to avoid field ID collision.

I'm not sure what you mean here. There is no prefix to field names that are used in a repeater. For example, if you have the "title" field in your containing page template, and also the title field in your repeater template then the field name "title" applies to both without any prefix.

echo $page->title; // the containing page title
echo $page->my_repeater->first->title; // the first repeater item's title

Or do you mean that in Page Edit the inputfields inside a repeater have a suffix to their name, e.g. "title_repeater1147"? Because you don't need to use that when you get the field in your template.

  • Like 2
Link to comment
Share on other sites

@Robin S I mean when I create fields for a repeater, let's say I need an image, an icon, and text, I assign them IDs prefixed with the repeater ID, so I create 3 fields named "home_tabs_image", "home_tabs_icon", and "home_tabs_text" and add them to the "home_tabs" repeater. Your reply made me realize I've been going at it like a neanderthal, and I don't actually need to create unique fields for a repeater, I just need to create each type of field I'll need once and I can assign them multiple times to different templates and repeaters. Boy, do I feel dumb right now :lol:.

Link to comment
Share on other sites

2 hours ago, novalex said:

Boy, do I feel dumb right now :lol:

never mind, the simplicity of processwire was a big hurdle for many of us in the beginning ;):P

...and i'm still curious what setup would need lots of repeaters for structuring everything. usually you can keep everything very clean just by using different templates, different parents in the tree and doing the relations via pagefields. don't get me wrong. it's just my experience that whenever something felt complex/complicated it was most of the times a problem of my (or other forum users) setup :)

i wish you lots of happy aha-moments ;)

  • Like 3
Link to comment
Share on other sites

Yep, if I'd learned PW from the start I'd probably be better off, but I'm used to the WP + ACF way of doing things, so they creep into this PW project as well.

As for the setup, for example, I have a group of tabs on the homepage, and each tab has sections with an image, icon and text. I figured the best way to do this would be to have a repeater for the tabs themselves and a nested repeater for each tab's sections. I have a pretty short deadline, so I had to just jump in head-first and get the homepage done to show the client. I'll definitely need some time to learn the ropes properly, and then I'll be able to better think every field and template out from the start and make things simpler.

Thanks a lot, once again, to all of you who took the time to help a newbie out, I hope to return the favor sometimes.

  • 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

×
×
  • Create New...