Vlastní validace pole ve formulaři a zobrazení chyby live validace

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

Zdravím,

máme registrační formulář který ověřuje zda v DB se uživatel s daným username nevyskytuje

//FORMULAR
$form = new Form();

        $form->addText('username', '')
                ->setAttribute('class', 'form-control')
                ->setAttribute('placeholder', 'Uživatelské jméno ...')
                ->setRequired('Uživatelské jméno musí být vyplněno!')
                ->addRule(callback($this, 'usernameValidator'), 'Uživatelské jméno je obsazeno!');
$form->addText('email', '')
                ->setAttribute('class', 'form-control')
                ->setAttribute('placeholder', '@')
                ->addRule(Form::EMAIL, 'Není platný e-mail!')
                ->setRequired('Email musí být vyplněn!');

// VALIDACE
public function usernameValidator($username) {
        $value = $username->getValue();
        $users = $this->users->findAll()->where('username', $value)->count('*');
        if ($users > 0) {
            return FALSE;
        } else {
            return TRUE;
        }
    }

Validace probehne pokud je username v db vrati to to pocet > 0, takže to neprojde, ale problém je ten, že mě to nevypíše žádnou chybu u formu…

používám live validaci a rád bych aby info o volném uživatelském jméně jsem měl hned při vyplňování políčka tak jako u emailu to kontrolue zda je to platny email atd …

Dkuji za radu

Editoval wicked (15. 1. 2015 10:50)

wicked
Člen | 290
+
0
-

Ot@s napsal(a):

Jukni na Jan Škrášek: Server-side validace, ajaxem a automaticky

Velice děkuji za link, dost pěkné video a hlavně poučné :) Ani jsem nevěděl o Bs3FormRenderer :-)

Ještě jednou, děkuji

wicked
Člen | 290
+
0
-

Napadá mě ještě dotaz … @hrach tam při tvorbě ServerValidatedTextInput.php řiká, že se provádí jedna validace, proto tam dá break; …

Blbá otázka, ale co když potřebuji validovat řekněmě 5 polí?

Děkuji

EDIT: Psal jsem dřív než jsem zkusil … normálně to funguje když přidám pro další pole …

Editoval wicked (15. 1. 2015 21:19)

hrach
Člen | 1844
+
0
-

@wicked jo, funguje, protože je tím myšleno jedna serverová validace pro konkrétní input :-)

wicked
Člen | 290
+
0
-

hrach napsal(a):

@wicked jo, funguje, protože je tím myšleno jedna serverová validace pro konkrétní input :-)

@hrach
Jasný jasný, nějak mi to hned nedocvaklo :-)

wicked
Člen | 290
+
0
-

Jak by se tam dalo napojit jeste overeni dat v DB? Nejak to nemuzu vymyslet …

wicked
Člen | 290
+
0
-

Napadlo mě toto:

$input->addServerRule(function(IControl $control) {
            return $control->getValue() !== $this->usernameValidator;
        }, 'Toto uživatelské jméno již existuje!');

a

public function usernameValidator($username) {
        $value = $username->getValue();
        $users = $this->users->findAll()->where('username', $value);
        foreach ($users as $user) {
           return $user->username;
        }
    }

Ale to jaks inefunguje .. nic to neudela

Mysteria
Člen | 797
+
0
-

Něco jako tohle nefunguje?

$input->addServerRule(function($control) {
	return !$this->users->findAll()->where('username', $control->value);
}, 'Uživatelské jméno není volné');

Editoval Mysteria (16. 1. 2015 12:15)

wicked
Člen | 290
+
0
-

Mysteria napsal(a):

Něco jako tohle nefunguje?

$input->addServerRule(function($control) {
	return !$this->users->findAll()->where('username', $control->value);
}, 'Uživatelské jméno není volné');

To jsem zkoušel, ale to vratí u každého pokusu že uživatel již existuje …

wicked
Člen | 290
+
0
-

Už jsem to vyřešil … jen doufám, že je to dobře :)

$input->addServerRule(function(IControl $control) {
            $data = $this->users->findAll()->where('username', $control->value)->fetch();
                return $control->getValue() !== $data->username;
        }, 'Toto uživatelské jméno již existuje!');
wicked
Člen | 290
+
0
-

@hrach měl bych na Tebe ještě jednu otazku, studoval jsem Tvůj kód ale nějak nevím jak jej upravit aby fungoval tahle:

když vyplníš špatné údaje políčka zčervenají a vypíše se chyba, to je ok, ale jak udělat to, když jsou údaje korektní, tak aby políčka zezelenala? neco jako has-success v bs3

wicked
Člen | 290
+
0
-

A beru zpět …

Když mám tento kód:

$input = $form['username'] = new \ServerValidatedTextInput('Uživatelské jméno:');
        $input->addRule($form::MIN_LENGTH, 'Uživatelské jméno musí mít minimálně %d znaků!', 5);
        $input->addServerRule(function(IControl $control) {
            $data = $this->users->findAll()->where('username', $control->value)->fetch();
            return $control->getValue() !== $data->username;
        }, 'Toto uživatelské jméno již existuje!');

Tak live validace funguje, ale jakmile chci form odeslat hodí me to:
Trying to get property of non-object

a odkazuje to na toto:

return $control->getValue() !== $data->username;

Napadá Vás někoho něco?

Editoval wicked (16. 1. 2015 18:25)

Jan Mikeš
Člen | 771
+
0
-

Mas spatne ten callback – fetch vraci ActiveRow nebo false pokud nenajde a ty tam mas $data->username i v pripade ze ten row nenajde, proto ta vyjimka.

Myslim ze takhle by to mohlo fungovat:

	$input = $form['username'] = new \ServerValidatedTextInput('Uživatelské jméno:');
        $input->addRule($form::MIN_LENGTH, 'Uživatelské jméno musí mít minimálně %d znaků!', 5);
        $input->addServerRule(function(IControl $control) {
            return($this->users->findAll()->where('username', $control->value)->fetch() && TRUE);
        }, 'Toto uživatelské jméno již existuje!');

Pro lepsi citelnost kodu by bylo dobre si ve tvem $users udelat nejakou metodu a pak vysledny kod by cisteji mohl vypadat takto:

	function findUser($username)
	{
		return $this->findAll()
			->where("username", $username)
			->fetch();
	}

	$input = $form['username'] = new \ServerValidatedTextInput('Uživatelské jméno:');
        $input->addRule($form::MIN_LENGTH, 'Uživatelské jméno musí mít minimálně %d znaků!', 5);
        $input->addServerRule(function(IControl $control) {
            return($this->users->findUser($control->value) && TRUE);
        }, 'Toto uživatelské jméno již existuje!');

Editoval Lexi (16. 1. 2015 18:58)

wicked
Člen | 290
+
0
-

Lexi napsal(a):

Mas spatne ten callback – fetch vraci ActiveRow nebo false pokud nenajde a ty tam mas $data->username i v pripade ze ten row nenajde, proto ta vyjimka.

Myslim ze takhle by to mohlo fungovat:

	$input = $form['username'] = new \ServerValidatedTextInput('Uživatelské jméno:');
        $input->addRule($form::MIN_LENGTH, 'Uživatelské jméno musí mít minimálně %d znaků!', 5);
        $input->addServerRule(function(IControl $control) {
            return($this->users->findAll()->where('username', $control->value)->fetch() && TRUE);
        }, 'Toto uživatelské jméno již existuje!');

Pro lepsi citelnost kodu by bylo dobre si ve tvem $users udelat nejakou metodu a pak vysledny kod by cisteji mohl vypadat takto:

	function findUser($username)
	{
		return $this->findAll()
			->where("username", $username)
			->fetch();
	}

	$input = $form['username'] = new \ServerValidatedTextInput('Uživatelské jméno:');
        $input->addRule($form::MIN_LENGTH, 'Uživatelské jméno musí mít minimálně %d znaků!', 5);
        $input->addServerRule(function(IControl $control) {
            return($this->users->findUser($control->value) && TRUE);
        }, 'Toto uživatelské jméno již existuje!');

Tohle mi zase hodí že uživatel již existuje i když neexistuje …

EDIT: To mám v plánu, jakmile bude vše fungovat tak jak má, přesunu veškerou práci s DB do modelů, teď potřebuji jen vyřešit funkčnost :)

Editoval wicked (16. 1. 2015 19:03)

Jan Mikeš
Člen | 771
+
0
-

Tak je chybka nekde asi u tebe, ta podminka je 100% spravne, ted jsem to testoval:

// email "some@mail.com" je v databazi
$test = ($this->userEntity->findAll()->where("email", "some@mail.com")->fetch() && TRUE); // vraci TRUE
$test = ($this->userEntity->findAll()->where("email", "some@me.comm")->fetch() && TRUE); // vraci FALSE

Editoval Lexi (16. 1. 2015 19:25)

wicked
Člen | 290
+
0
-

Tak jsem to vyřešil takto, ale bojím se, že je to velká prasečina …

// Uzivatelske informace
        $input = $form['username'] = new \ServerValidatedTextInput('Uživatelské jméno:');
        $input->addRule($form::MIN_LENGTH, 'Uživatelské jméno musí mít minimálně %d znaků!', 5);
        $input->addServerRule(function(IControl $control) {
            if ($data = $this->users->findAll()->where('username', $control->value)->fetch()) {
                return $control->getValue() !== $data->username;
            } else {
                return $control->getValue() !== '';
            }
        }, 'Toto uživatelské jméno již existuje!');
        $input->setAttribute('placeholder', 'Vaše uživatelské jméno ...');
        $input->setRequired('Uživatelské jméno musí být vyplněno!');

Avšak funkční …