Jump to content

PageField – limit number of choices


a-ok
 Share

Recommended Posts

Hi folks,

I have a simple PageField set up, which is being used in this instance as a 'Related Articles' area; they can choose (Multiple Pages) which news articles are related then it does something nice front end. The only issue I have is that I'd like to limit the number of articles they can choose (only allowing three, for example) much like you would have in a File field or Image field (Maximum files allowed).

Any thoughts?

Link to comment
Share on other sites

I'm talking about the inputfield you choose the page field to use, e.g. Select, ASMSelect, PageListSelect and so on. These all work differently in terms of markup and javascript, so it's understandable that there's no central way to limit the number of selections beyond single / multiple. Single and Multiple pagefields are even mostly using different inputfields. 

Link to comment
Share on other sites

You can always strip off additional pages using php, but that's certainly not the best user experience. For the ASM Select you could create a javascript, which does disable all options from the select box if a certain number of pages was selected (and reset if not).

Link to comment
Share on other sites

nice challenge for the evening with a happy end :)

create a javascript file scripts/limitpageselect.js: 

// my field is called "pageselect"
$(window).load(function() {
    if($('#Inputfield_pageselect :selected').length > 4) $('#Inputfield_pageselect').siblings('select').hide();
    $('#Inputfield_pageselect').change(function() {
        if($('#Inputfield_pageselect :selected').length > 4) {
            $(this).siblings('select').hide();
        }
        else {
            $(this).siblings('select').show();
        }
    });
});

and inject this file via hook in /site/ready.php

$wire->addHookAfter("ProcessPageEdit::buildForm", function(HookEvent $event){
    $process = $event->object;
    $page = $process->getPage();

    if($page->template != 'basic-page') return; // set your template name here

    $config = wire('config');
    $config->scripts->append($config->urls->templates . 'scripts/limitpageselect.js');
});

post-2137-0-99193100-1448405819_thumb.gi

  • Like 7
Link to comment
Share on other sites

I see, but in ready.php the $page is already determined, isn't it?

This snippet actually works:

// content in ready.php

if ($page->template != 'admin') {
    $wire->addHookAfter("Page::render", function (HookEvent $event) {
        echo <<< HTML
    <script type="text/javascript">alert('Hello world');</script>
HTML;
    });
}

I guess it's because it hooks to Page:: render.

Link to comment
Share on other sites

hi tpr,

this method works in frontend but not in admin! try

echo $page->id;

it will show "10" for all processpageedit pages... /admin/setup/ would be 22

unfortunately there's a bug in my script: when you save a field with 5 pages it will not remove the select-field because its only called on change of the field. the problem is, that the select-field is injected by jquery by the admin so this does not work:

// my field is called "pageselect"
$(function() {

    $('#Inputfield_pageselect').siblings('select').hide(); // added this line

    $('#Inputfield_pageselect').change(function() {
        if($('#Inputfield_pageselect :selected').length > 4) {
            $(this).siblings('select').hide();
        }
        else {
            $(this).siblings('select').show();
        }
    });
});

maybe it would work if the script was loaded at the very last of all scripts?

post-2137-0-12119600-1448442893_thumb.pn

how could i achieve that?

Link to comment
Share on other sites

Hi BernhardB,

I have a small module that injects a script tag right before </body>. Here's the relevant lines

	public function init() {

		$this->addHookAfter('Page::render', $this, 'addInlineScript'); 

	}

	public function addInlineScript($event) {

		$page = $event->object;

		if ($page->template->name !== "admin" && $page->inlineScript) {

			$event->return = str_replace("</body>", $page->inlineScript . "</body>", $event->return);

		}

	}

You can adjust that to your situation. Hope it helps.

  • Like 1
Link to comment
Share on other sites

Some improvements in the JS:

$(window).load(function () {

    var fieldName = 'tags_recipe',  // add field name here
        limit = 5,  // set limit here
        asmSelector = '#Inputfield_' + fieldName;

    $(asmSelector).on('change limitItems', function () {
        var obj = $(this).parent().find('.asmSelect');
        $(this).find(':selected').length >= limit ? obj.attr('disabled', 1) : obj.removeAttr('disabled');
    });

    $(asmSelector).trigger('limitItems');
});

What would be nice is to add the "limit" in the backend to the asmSelect using a "data-limit" attribute and then let JavaScript do its part on all asmSelects which have data-limit set.

  • Like 5
Link to comment
Share on other sites

  • 2 years later...

It's done, will be added to the next aos update. I've borrowed some code from @Robin S modules (thanks!) as I haven't added config inputs to fields so far.

In fact I totally forgot about this asmSelect snippet of mine, thanks for the reminder :)

 

limitasmselect01.png

limitasmselect.gif

  • Like 5
  • Thanks 1
Link to comment
Share on other sites

6 hours ago, Robin S said:

Do you reckon you could do something similar for Page Autocomplete?

I saw this follow-up question coming, ? I think that's also doable, will check that later. I reckon the same question is about to emerge for the rest of the PageField types, isn't it? ?

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