Validace formulářů – možnost validace pouze některých containerů/prvků

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Foowie
Člen | 269
+
0
-

Tuhle fíčuru už jsem několikrát potřeboval, zatím je stav

public function setValidationScope($scope)
{
	// TODO: implement groups
	$this->validationScope = (bool) $scope;
	return $this;
}

Jedná se o změnu celkem 3 metod, takže pokud by byl čas, tak by nebylo špatné to dodělat.
Lehký nástřel jak by fix mohl vypadat (pro Nette 1.0-dev) je níže:

SubmitButton

public function setValidationScope($scope)
{
	$this->validationScope = $scope;
	$this->control->data("nette-scope", is_array($scope) ? implode(" ", $scope) : $scope);
	return $this;
}

FormContainer

public function validate()
{
	$this->onValidate($this);
	$name = ($this instanceof Form) ? "" : $this->lookupPath("Form");
	$submit = $this->getForm()->isSubmitted();
	if($submit === false)
		$scope = true; // is not submitted -> validate all items
	else {
		$scope = $submit->getValidationScope();
		if($scope === false)
			return $this->valid = true;
	}
	if($scope === true)
		$scope = array("");
	else if(is_string($scope))
		$scope = array($scope);
	$validate = !(is_array($scope) && !in_array($name, $scope, true));

	$this->valid = TRUE;
	if($validate) { // validate all components
		foreach ($this->getControls() as $control) {
			if (!$control->getRules()->validate()) {
				$this->valid = FALSE;
			}
		}
	} else { // validate only containers
		foreach($this->getComponents(false, "FormContainer") as $container)
			if(!$container->isValid())
				$this->valid = false;
	}
}

A nakonec ještě změna v netteForms.js

<script>
nette.validateForm = function(sender) {
	var form = sender.form || sender;
	if (form['nette-submittedBy'] && form.elements[form['nette-submittedBy']].getAttribute('data-nette-scope')) {
		var scopes = form.elements[form['nette-submittedBy']].getAttribute('data-nette-scope').split(" ");
		for (var i = 0; i < scopes.length; i++) {
			var splited = scopes[i].split("-");
			var first = splited.shift();
			scopes[i] = first + ((splited.length > 0) ? "[" + splited.join("][") + "]" : "");
		}
		for (i = 0; i < form.elements.length; i++) {
			var doValidate = false;
			for(var j = 0; j < scopes.length; j++) {
				var elementName = form.elements[i].name;
				var scopeName = scopes[j];
				if(scopeName == "1" || elementName.indexOf(scopeName) === 0 && (elementName.length == scopeName.length || elementName.length > scopeName.length && elementName[scopeName.length]  == "[")) {
					doValidate = true;
					break;
				}
			}
			if (doValidate && !nette.validateControl(form.elements[i]))
				return false;
		}
	}
	return true;
}
</script>

A použití:

$submitButton->setValidationScope(true); // celý form
$submitButton->setValidationScope(false); // nic
$submitButton->setValidationScope("container"); // pouze container "container"
$submitButton->setValidationScope("container-subcontainer"); // pouze container "subcontainer" v containeru "container"
$submitButton->setValidationScope(array("container1", "container2")); // pouze "container1" a "container2"

Btw je to jenom nástřel…