Jump to content

PageField – limit number of choices


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 post
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 post
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 post
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 post
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 post
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 post
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 post
Share on other sites

thank you!

i was already using document.ready (short syntax) - gebeer was right, both injecting the JS via str_replace(</body> and loading the script via window.onload worked!

i updated the code above so it should be working now.

Link to post
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 post
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
Link to post
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 post
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 rjgamer
      Hi,
      is there a hook after the current (active) page got created? Or which method got called in the Page class after the Constructor of the current page got initialized?
      Thanks.
       
    • By rjgamer
      Hi guys,
      the field "redirect_last" of type DateTime got not updated. The update on the field "redirect_counter" works and got saved.
      Does anybody know what I did wrong in my code?
      if ($input->urlSegment(1) === 'redirect') { $page->of(false); $page->redirect_last = time(); $page->redirect_counter += 1; if ($page->save('redirect_counter')) { $session->redirect($page->website_url, 302); } } Thanks.
    • By theoretic
      Hi there! And thanks for Processwire!
      I have an interesting task which i cannot fulfill as i want. Maybe someone could help me please?
      Let's imagine a simple page structure of this kind:
      Category 1
      + Item 1.1
      + Item 1.2
      Category 2
      + Item 2.1
      + Item 2.2
      My task is to attach some items to more than one category, at least to show some items on different frontend category pages. With PW, it's a piece of cake. I've just created a field called Items (of type Page Reference) and attrached it to Category template. Since i have lots of items inside each category i preferred to use Page Autocomplete input for my Items field. The pages available for autocomplete are restricted by a very simple selector:
      template=item
      It works like a charm. But later i decided to make this autocomplete even smarter and to exclude current category children items from it. I tried to update my selector this way...
      template=item,parent!=(page)
      ...and oops, this broke my selector. My autocomplete founds nothing. Sorry, i had to replace the square braces by () because of this forum limitations, i swear i'm using square brackets in real-life selector!
      What am i doing wrong? And is there any way to include current page info in autocomplete-related selectors? Thanks in advance!
       
    • By louisstephens
      So I ran into a very strange issue today. I have a template with a pagetable and I went to add an item to it, when I went to select an image (for an image field) the page instantly threw up an error
      "ProcessPageSearchLive: No search specified"
      The page's content also switched to the image attached. This all worked perfectly last week (local mamp box). Has anyone experienced this before, and how did you solve it?
       

    • By Pip
      Hi everyone, 
      Is there a way for us to replicate the "http://mydomain.com/processwire/page/edit/?id=xxx" and change the template to match my site template? 
      I'm terribly happy with the admin / backend page edit. It covers literaly everything I want to empower my non super admin user in updating pages such as validation, repeater management, file upload. 
      I wish not to allow the users to see the backend for both security and aesthetic reasons. 
      Thanks and hope to hear from you soon. 
       
×
×
  • Create New...