Jump to content

extending inputfields


Frank Vèssia
 Share

Recommended Posts

I'm building a form builder based on the original inputfileds of PW. Now i'm at the point in which i have the same form in the admin and in the frontend, changing a field in the admin my form change in the same way, same for the post action. Now i want to add the automatic validation for every field and for making this i need to add a select near every inputfield in the admin for choose the right validator.

Link to comment
Share on other sites

I think I understand. I should say though that PW's fields and inputs are designed for administrative use rather than front end use. If I'm building something for the front end, I might still use PW pages to store the data, but I'm handling the input on my own and populating fields into page objects. That's what I recommend because you'll be able to do whatever you want without limitation and use PW's API in the manner it was built for.  But if the Inputfields are suiting your need, then here's what you'd do to extend all of them. In the example, we add a hook to the field rendering (to add a select box with each one) and another hook to the input processing.

This example module should be pasted into a file called /site/modules/InputfieldHookTest.module

<?php

class InputfieldHookTest extends WireData implements Module {

public static function getModuleInfo() {	
	return array(
		'title' => 'Inputfield Hook Test',
		'version' => 100,
		'summary' => 'Just a test.',
		'singular' => true,
		'autoload' => true,
		);
}

public function init() {
	$this->addHookAfter('Inputfield::render', $this, 'render'); 
	$this->addHookAfter('Inputfield::processInput', $this, 'processInput'); 
}

public function render(HookEvent $event) {
	$inputfield = $event->object;

	// optional, but better to limit to those you want
	if(!$inputfield instanceof InputfieldText && !$inputfield instanceof InputfieldTextarea) return; 

	$name = $inputfield->name;  
	$event->return .= "<p><select name='test_$name'><option></option><option>test</option><option>test2</option></select></p>";
}

public function processInput(HookEvent $event) {
	$inputfield = $event->object; 
	$name = $inputfield->name; 
	$post = $event->arguments[0];
	$value = $post["test_$name"]; 
	if($value) $this->message("You selected '$value' for '$name'"); 
}

}
  • Like 2
Link to comment
Share on other sites

that kinda was what I was asking for here http://processwire.com/talk/index.php/topic,465.0.html :)

I already was this far to have the right hook on inputfields and all but missed the obvious, that playing with str_replace I replaced itself each recursion... was late night. 

Thanks for the example that helped and made some things clearer.

Link to comment
Share on other sites

  • 3 years later...

I'm trying to create a slightly enhanced page select, whereby the only difference to the output would be adding a data-description to each option, which would be populated by looking up the value of a data-description field on that selectable page;

I know where (renderOptions function) to make the change, but not sure how to hook in there and replace that function, or should i make a new inputfield for this? I did try copying the InputfieldSelect and making some changes (calling it InputfieldSelectEnhanced), and but i'm not clear how to get this new inputfield to show up in the list of options for the Fieldtype Page...

ultimately the goal would be to use javascript to replace the description area below the page select with the data for that particular select; for a simple example, say I have a select on a page that specifies actions that will take place on save (like importing files, or deleting files from the page etc..), i would like to have a more descriptive paragraph about what exactly my save action will do..

this would be sort of useful just about anytime you needed to show the user more information about what they have selected, beyond just the title, and where that info is going to be a little verbose (and wouldn't work as the option label)..

thanks!

Link to comment
Share on other sites

Hi Macrura,
 
I've just done something similar to this for my current project. I needed to add data-start-time attributes to every option in a select dropdown so I decided to extend the InputfieldSelectMultiple class to provide a replacement addOption() implementation that added the required data attribute as part of the internal attributes array for each option. Here's what I did...

public function addOption($value, $label = null, array $attributes = null)
{
    if (
        is_null($value) ||
        (is_string($value) && !strlen($value))
    ) {
        return $this;
    }

    if (null === $attributes) {
        $attributes = array();
    }

    $extra_atts = $this->extendAttributes($value, $label);
    $attributes = array_merge($attributes, $extra_atts);

    return parent::addOption($value, $label, $attributes);
}

public function ___extendAttributes($id, $value)
{
    $atts = array();
 
    /**
     * Either hook this method to do what you want or implement things directly if this
     * is the only use of this Inputfield. 
     * For your example you'd grab the fields you want from your page and put into data
     * attributes...
     */
    //$page   = wire()->pages->get($id);
    //$atts['data-description'] = $page->description;

    return $atts;
}

I've updated the example above to output data-description. 

Hope that helps you with some ideas!

  • Like 8
Link to comment
Share on other sites

w.o.w. !  netcarver - thanks -this is going to be amazing, and i don't think i could have figured this out, at least not for a while..

so (this being the first time i'm doing this more advanced sort of module), could you possibly explain a tiny bit more about how to extend the class (say for InputfieldSelect) - where or what sort of module would i create to place that code?

TIA

Link to comment
Share on other sites

Hi Macrura,

Here's a version for select multiple...

<?php

class InputfieldSelectMultipleExtended extends InputfieldSelectMultiple
{
    public static function getModuleInfo()
    {
        return array(
            'title'     => __('Select Multiple Extended', __FILE__),
            'version'   => 1,
            'summary'   => __('Multiple selection with extended attributes. An enhancement to select multiple', __FILE__),
            'permanent' => false,
        );
    }

    /**
     * Adds an option with extended attributes
     */
    public function addOption($value, $label = null, array $attributes = null)
    {
        if (
            is_null($value) ||
            (is_string($value) && !strlen($value))
        ) {
            return $this;
        }

        if (null === $attributes) {
            $attributes = array();
        }

        $extra_atts = $this->extendAttributes($value, $label);
        $attributes = array_merge($attributes, $extra_atts);

        return parent::addOption($value, $label, $attributes);
    }

    /**
     * Hook this and return an array with whatever extended attributes you need.
     *
     */
    public function ___extendAttributes($id, $value)
    {
        $atts = array();

        /**
         * Either hook this method to do what you want or implement things directly if this
         * is the only use of this Inputfield.
         * For your example you'd grab the fields you want from your page and put into data
         * attributes...
         */
        $page = wire()->pages->get($id);
        $atts['data-description'] = $page->description;

        return $atts;
    }
}

Here's how to use it...

  • Save this module as InputfieldSelectMultipleExtended.module in your site/modules directory of a development install of PW.
  • Install it in PW.
  • Edit InputfieldPage's module configuration and add InputfieldSelectMultipleExtended to the inputfields that can represent pages.
  • Create a new Page field and select InputfieldSelectMultipleExtended on the input tab and setup the parent and other fields as required.
  • Add the new page reference field to a template.
  • Add some pages that use this template.
  • Check the HTML of any of the pages using the template and you should see the options for the select have data-description attribute for every page referenced that has a non-empty description field. 

Hope that helps!

  • Like 8
Link to comment
Share on other sites

@netcarver - can't thank you enough -this completely works!! :biggrin:

I added a js file to populate my description field above the select, and changed the module name to be select, not multiple.. will have to do a screenshot/screencast; 

this module should be made available in some form on the directory, as i think it has some great use cases for data- attributes on selects...

maybe both versions, select and select multiple

  • Like 2
Link to comment
Share on other sites

Here's an example of how I used the module that netcarver posted:

before something is selected:

post-136-0-62362600-1413379410_thumb.png

after selection:

post-136-0-64257300-1413379414_thumb.png

i also had an idea for extending AsmSelect to make the selected items clickable and brings up a modal editor for that selected page; has anyone done something like that yet? For example with this site I'm working on, you can add composers to a track, but it would be cool if after you add new items to the page you could click on them to make some edits (bio, website for ex), without having to go and find that page in the tree..

  • Like 2
Link to comment
Share on other sites

@Macrura

Glad this worked out for you.

Actually, the PW admin interface does what you are after already (if I understand you correctly.)  If you edit a template and look at the AsmSelect list of fields in the template - each one of them is clickable and brings up a modal edit for that field's properties when used in that particular template. This would suggest that everything you need is already built right into AsmSelect so I'd suggest you have a look through the source code and see what's commented in there and how Ryan uses it.

  • Like 3
Link to comment
Share on other sites

@netcarver - yes, that's what I was thinking, and have been sort of studying that now for a few hrs; i came up with a quick solution using jquery for now.. ( https://processwire.com/talk/topic/8005-page-select-edit-links/?p=77312 ) but it would be nice if there could be a simple toggle on every page select field, like "title links to edit" ..

Link to comment
Share on other sites

  • 1 year later...

@Macrura @horst

I've added this feature request to the new repo - please emoti-vote for it if you still want this as a core feature.

As a side note, here are some screenshots of a module that I ended up developing in the absence of this feature. Take a standard ASM Select...

shot-001.png

...add some extended data attributes to the options...

extended-options-asm-select.png

...and a little javascript to use the data-group attribute of the selected options to disable other, currently unselected options with a matching data-group value (all while keeping things in the right sort order.) You then get a list that prevents your gymnasts from being booked in to the Trampoline group at the same time they are already booked in the Gymnastics group...

extended-functionality-asm-select.png 

 

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