Jump to content

Add field to specific position in existing template


didhavn
 Share

Recommended Posts

Hey All.

I am currently writing a very small module to accomplish the following:

- I have a Page "Service Types" with multiple childs "Service Type". Whenever a new "Service Type" is added, a Field (in my case FieldtypeRangeSlider) should be generated, eg "servicetype_communication_rangeslider" and added to an existing template ('case') at a specific position.

I have little experience with modules but managed to get it done till the successfull creation of the range-field.

But now I am struggeling with adding it to the template.

First, I havend managed to get a list of templates in the module..just a workaround via pages and selector template=case. I think this would work, but only of there are pages with this tempalte. If not, this solution fails and in general, I don't know how to get the templates in a module.

Second, I have no clue how to add a field at a specific position to an existing template (to an existing Fieldset in my case).

Here is my code so far:

class AddServiceTypesByPage extends WireData implements Module {
	
	public static function getModuleInfo() {
		return array(
			'title' => 'Add ServiceTypes By Page (Didhavn)',
			'version' => 1.0,
			'summary' => 'Add the ServiceTypes by getting Pages with Template "service-type"',
			'singular' => true,
			'autoload' => true
		);
	}
	public function init() {
		$this->pages->addHookAfter('added', $this, "hookAdded");
	}
	public function ready() { 
		// PW API is ready, Controllers go here		
	}
	public function hookAdded(HookEvent $event) {
		$page = $event->object;
		if (!$page->template) {
			$page = $event->arguments[0];
		}
		if($page->template == 'service-type') {
			$f = new Field();
			$f->type = $this->modules->get("FieldtypeRangeSlider");
			$f->name = 'servicetype_' . $page->name;
			$f->label = 'Service-Type ' . $page->get('title')->getDefaultValue();
			$f->set('suffix','%');
			$f->set('tags','servicetype');
			$f->set('icon','fa-sliders');
			$f->save();
			/*
			 * now add the field to existing template with name 'case'
			 */
		}
	}

}

I am thankfull for any help or suggestion!

Thanks a lot!

  • Like 1
Link to comment
Share on other sites

Firstly, welcome to the forums, didhavn!

And secondly, apologies for a rubbish answer, but it must be possible to insert a field at a specific point because you can do it in the backend, under 'Actions' (I think), when creating a new field. You might be able to find it in the code.

Someone will be along soon with a better answer, I'm sure.  :-[

Link to comment
Share on other sites

This should do it - just change "body" to the name of the existing field that you want to insert before. You can of course change insertBefore to insertAfter if that is easier/needed.

if($page->template == 'service-type') {
    $f = new Field();
    $f->type = $this->modules->get("FieldtypeRangeSlider");
    $f->name = 'servicetype_' . $page->name;
    $f->label = 'Service-Type ' . $page->get('title')->getDefaultValue();
    $f->set('suffix','%');
    $f->set('tags','servicetype');
    $f->set('icon','fa-sliders');
    $f->save();
    $existingField = $page->template->fieldgroup->fields->get("body");
    $template = $page->template;
    $template->fieldgroup->insertBefore($f, $existingField);
    $template->fieldgroup->save();
}

Here's a relevant section from the core ProcessField module that shows this in action: https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/modules/Process/ProcessField/ProcessField.module#L1850

Edited by adrian
Tested and tweaked, so should now be working.
  • Like 2
Link to comment
Share on other sites

Hey DaveP and adrian.

Wow, I have heard that the PW community is fast and helpfull...but THIS fast? Thanks a lot, I will give it a try and hope that I will get is working.

But a general questions remains....up to now, I wasn't able to get the list of templates in the module via e.g.

$templates = wire('templates');

I need to add this field to a different template than the current and was only able to get this template via

$currtmpl = $event->pages->find('template=case')[0]->template;

Suppose I don't have a page with template case, this solution fails. Is there another possibilty to get the template 'case' without querying the pages?

Thanks a lot!!

Link to comment
Share on other sites

I don't understand why you can't get a list of templates via wire('templates').

foreach(wire('templates') as $t) {
    echo $t->name . '<br />';
}

will give you a list of template names.

As for adding the field to the template of a different page, this works - just watch $this vs wire() depending on your module setup.

$f = new Field();$f->type = $this->modules->get("FieldtypeRangeSlider");
$f->name = 'servicetype_' . $page->name;
$f->label = 'Service-Type ' . $page->get('title')->getDefaultValue();
$f->set('suffix','%');
$f->set('tags','servicetype');
$f->set('icon','fa-sliders');
$f->save();

$template = $this->templates->get("name_of_other_template");

$existingField = $template->fieldgroup->fields->get("body"); 
$template->fieldgroup->insertBefore($f, $existingField); 
$template->fieldgroup->save();

Maybe we need to see some more of your module code to help with the $event and getting the template from that?

Link to comment
Share on other sites

I don't know why I get an empty Templates Object executing

$this->message(wire('templates'));

I can only get wire('pages'), nothing else.

My module code is just this one class I posted above...nothing else. Maybe I have to implement some other classes?

Link to comment
Share on other sites

Aaaah, I didn't know that wire('templates') or $this->templates can be shown as an empty array in the $this->message output BUT still return something when doing

foreach(wire('templates') as $t) {
    echo $t->name . '<br />';
}

or

$this->templates->get("name_of_other_template")

Thanks a lot for your help, after realizing that, the rest was easy!

<?php

/**
 * ProcessWire module to create ServiceTypes by Pages
 * by Didhavn
 * 12.02.2016
 */

class DidhavnAddServiceTypesByPage extends WireData implements Module {
	
	public static function getModuleInfo() {
		return array(
			'title' => 'Add ServiceTypes By Page (Didhavn)',
			'version' => 1.0,
			'summary' => 'Add the ServiceTypes by getting Pages with Template "service-type"',
			'singular' => true,
			'autoload' => true
		);
	}
	public function init() {
		$this->pages->addHookAfter('added', $this, "hookAdded");
	}
	public function ready() { 
		// PW API is ready, Controllers go here		
	}
	public function hookAdded(HookEvent $event) {
		$page = $event->object;
		if (!$page->template) {
			$page = $event->arguments[0];
		}
		if($page->template == 'service-type') {
			$newfieldname  = 'servicetype_' . $page->name;
			$newfieldlabel = 'Service-Type ' . $page->get('title')->getDefaultValue();
			$casetmpl = $this->templates->get("case");
			$newfield = $this->fields->get($newfieldname);
			if (!$newfield && $casetmpl) {
				// field for this service-type doesn't exist -> create
				$f = new Field();
				$f->type = $this->modules->get("FieldtypeRangeSlider");
				$f->name = $newfieldname;
				$f->label = $newfieldlabel;
				$f->set('suffix','%');
				$f->set('tags','servicetype');
				$f->set('icon','fa-sliders');
				$f->save();
				// add field to template case
				$stsumfield = $casetmpl->fieldgroup->fields->get("servicetype_sum");
				$casetmpl->fieldgroup->insertBefore($f, $stsumfield);
				$casetmpl->fieldgroup->save();
			}
		}
	}

}
  • Like 1
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...