Jump to content

Custom validation for Repeater


landitus
 Share

Recommended Posts

I've been trying to do the following:

I have 2 repeaters in a template and a I want to limit those repeaters to a number stored in another page. That number is then called in the template via a Select field (which is a Page relation). So when the user is editing the page, if the select says 3, then there are only 3 items allowed in the repeater. Should the user create 4, then a validation error should show up. 

How difficult is this to achieve? I've been reading this related thread but I still don't get it.

Link to comment
Share on other sites

  • 2 weeks later...

One of the next items on the to-do list for repeaters it to be able to specify a max number of items, but I'm not sure that would accomplish what you are looking for here. Your best bet may be a hook after ProcessPageEdit::processInput to look at the values of both fields. I would suggest setting your repeater "ready" items at 0, so that it is less to consider when counting the values. You could put this, or something like it at the top in your /site/templates/admin.php file:

<?php

wire()->addHookAfter('ProcessPageEdit::processInput', null, 'checkRepeaterQuantity'); 

function checkRepeaterQuantity($event) {
  $form = $event->arguments(0);

  // ProcessPageEdit's processInput function may go recursive, so we want to skip
  // the instances where it does that by checking the second argument named "level"
  $level = $event->arguments(1);
  if($level > 0) return; 

  $select  = $form->get("your_quantity_select_field");
  if(!$select) return;
  $quantity = $select->attr('value'); 

  $repeater = $form->get("your_repeater_field"); 
  if(!$repeater) return;

  if(count($repeater) > $quantity) {
    $repeater->error("You have specified more than $quantity items"); 
  }
}
 
  • Like 1
Link to comment
Share on other sites

Thanks Ryan for the answer. I'm closer to understand how this could work. I chose to put the code inside a module, as I found it easier to test. I'm getting blocked by the following: No matter how many items the repeater has, the count always equals "1". I tried to use a $form->get("calculadora_inputs")->count(), or children but I get a huge error that this is not allowed.

Let me post the code:

<?php

class ProcessValidateCalculator extends WireData implements Module {

	/**
	 * getModuleInfo is a module required by all modules to tell ProcessWire about them
	 *
	 * @return array
	 *
	 */
	public static function getModuleInfo() {

		return array(

			
			'title' => 'Validate Calculator', 
			'version' => 101, 
			'summary' => '',
			'href' => '',
			'singular' => true, 
			'autoload' => true, 
			);
	}
	public function init() {
		$this->addHookAfter('ProcessPageEdit::processInput', $this, 'checkRepeaterQuantity');
	}
	
	public function checkRepeaterQuantity($event) {
	  	$form = $event->arguments(0);

	  	// ProcessPageEdit's processInput function may go recursive, so we want to skip
	  	// the instances where it does that by checking the second argument named "level"
	  	$level = $event->arguments(1);
	  	if($level > 0) return; 

	  	// Simplified this part to test a simple quantity.
		$quantity = 1;
	  	$repeater = $form->get("calculadora_datos");
	  	if(!$repeater) return;

	  	if(count($repeater) > $quantity) {
	    	   $repeater->error("You have specified more than $quantity items"); 
	  	}
	        

	}
}
Link to comment
Share on other sites

I was able to calculate the correct amount of repeaters by passing a ->value to the field. So this worked pretty well. The curious thing I'm getting the form saved even thought the validation is not passing. I'm getting a session page saved notification no matter what. Is this supposed to happen with this code? or I have to prevent the validation manually?

<?php


class ProcessValidateCalculator extends WireData implements Module {

	/**
	 * getModuleInfo is a module required by all modules to tell ProcessWire about them
	 *
	 * @return array
	 *
	 */
	public static function getModuleInfo() {

		return array(

			
			'title' => 'Validate Calculator', 
			'version' => 101, 
			'summary' => '',
			'href' => '',
			'singular' => true, 
			'autoload' => true, 
			);
	}

	public function init() {
		$this->addHookAfter('ProcessPageEdit::processInput', $this, 'checkRepeaterQuantity');
	}
	
	public function checkRepeaterQuantity($event) {
	  	$form = $event->arguments(0);

	  	// ProcessPageEdit's processInput function may go recursive, so we want to skip
	  	// the instances where it does that by checking the second argument named "level"
	  	$level = $event->arguments(1);
	  	if($level > 0) return; 

	  	
	  	$calculadora  = $form->get("calculadora")->attr('value');
	  	if(!$calculadora) return;
	  	
	  	// Datos
	  	// =========================================
	  	$qty_datos = $calculadora->cant_datos; 
	  	$datos = $form->get("calculadora_datos");
	  	if(!$datos) return;
	  	// Validación: Datos
	  	if(count($datos->value) > $qty_datos) {
	    	$datos->error("El campo $datos->label tiene más items de los permitidos. $datos->label permitidos: $qty_datos"); 
	  	} else if(count($datos->value) < $qty_datos) {
	  		$datos->error("El campo $datos->label no tiene la cantidad de items necesarios. $datos->label necesarios: $qty_datos");
	  	}
}
}
Link to comment
Share on other sites

Is your error message still appearing? ProcessWire doesn't abort a save even if there was an error on some field, so that is normal behavior. Though it will prevent an unpublished page from being published if there is an error occurring. If you want to literally prevent the save from occurring, you may have to throw an exception. 

Link to comment
Share on other sites

  • 4 weeks later...

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...