Skip to content

Commit 1847faf

Browse files
author
Yuri Maltsev
committed
Merge pull request #44 from formapro/JsFormValidatorBundle-43
#43 Custom init #40 Init separated forms
2 parents 3bdeb99 + 1697a26 commit 1847faf

18 files changed

Lines changed: 448 additions & 38 deletions

File tree

.travis.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ before_script:
1313
- export DISPLAY=:99.0
1414
- sleep 4
1515

16-
- curl http://getcomposer.org/installer | php
17-
- php composer.phar require --no-update symfony/symfony=$SF_VERSION
18-
- php composer.phar install --dev
16+
- composer require "symfony/symfony":"${SF_VERSION}"
17+
- composer install -n
1918

2019
- Tests/app/console assets:install Tests/app
2120
- sudo chmod -R 0777 Tests/app/cache Tests/app/logs
2221
- sudo chmod 0777 Resources/public/js/fp_js_validator.js
22+
# just show the current directory tree
2323
- ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'
2424

2525
- sudo apt-get update > /dev/null
@@ -28,12 +28,12 @@ before_script:
2828
- sudo sed -i -e "s,/var/www,$(pwd)/Tests/app,g" /etc/apache2/sites-available/default
2929
- sudo /etc/init.d/apache2 restart
3030

31-
- curl http://selenium.googlecode.com/files/selenium-server-standalone-2.33.0.jar > selenium.jar
31+
- curl http://selenium.googlecode.com/files/selenium-server-standalone-2.35.0.jar > selenium.jar
3232
- java -jar selenium.jar > selenium.log &
3333
- sleep 4
3434

3535
script: phpunit -v
36-
after_script:
37-
- php vendor/bin/coveralls -v
36+
#after_script:
37+
# - php vendor/bin/coveralls -v
3838
after_failure:
3939
- cat selenium.log
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
namespace Fp\JsFormValidatorBundle\Exception;
3+
4+
class UndefinedFormException extends \Exception
5+
{
6+
7+
}

Factory/JsFormValidatorFactory.php

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
namespace Fp\JsFormValidatorBundle\Factory;
33

4+
use Fp\JsFormValidatorBundle\Exception\UndefinedFormException;
45
use Fp\JsFormValidatorBundle\Form\Constraint\UniqueEntity;
56
use Fp\JsFormValidatorBundle\Model\JsConfig;
67
use Fp\JsFormValidatorBundle\Model\JsFormElement;
@@ -153,6 +154,16 @@ public function createJsConfigModel()
153154
return $model;
154155
}
155156

157+
/**
158+
* Returns the current queue
159+
*
160+
* @return \Symfony\Component\Form\Form[]
161+
*/
162+
public function getQueue()
163+
{
164+
return $this->queue;
165+
}
166+
156167
/**
157168
* Add a new form to processing queue
158169
*
@@ -177,21 +188,32 @@ public function inQueue(Form $form)
177188
return isset($this->queue[$form->getName()]);
178189
}
179190

191+
/**
192+
* Removes from the queue elements which are not parent forms and should not be processes
193+
*
194+
* @return $this
195+
*/
196+
public function siftQueue()
197+
{
198+
foreach ($this->queue as $name => $form) {
199+
$blockName = $form->getConfig()->getOption('block_name');
200+
if ('_token' == $name || 'entry' == $blockName || $form->getParent()) {
201+
unset($this->queue[$name]);
202+
}
203+
}
204+
205+
return $this;
206+
}
207+
180208
/**
181209
* @return JsFormElement[]
182210
*/
183211
public function processQueue()
184212
{
185213
$result = array();
186-
187214
foreach ($this->queue as $form) {
188-
$name = $form->getName();
189-
$blockName = $form->getConfig()->getOption('block_name');
190-
if ('_token' != $name && 'entry' != $blockName && !$form->getParent()) {
191-
$model = $this->createJsModel($form);
192-
if ($model) {
193-
$result[] = $model;
194-
}
215+
if (null !== ($model = $this->createJsModel($form))) {
216+
$result[] = $model;
195217
}
196218
};
197219

@@ -527,17 +549,39 @@ public function getJsConfigString()
527549
}
528550

529551
/**
552+
* @param string $formName
553+
* @param bool $onLoad
554+
*
555+
* @throws \Fp\JsFormValidatorBundle\Exception\UndefinedFormException
530556
* @return string
531557
*/
532-
public function getJsValidatorString()
558+
public function getJsValidatorString($formName = null, $onLoad = true)
533559
{
534-
$models = $this->processQueue();
560+
$onLoad = $onLoad ? 'true' : 'false';
561+
$this->siftQueue();
562+
563+
$models = array();
564+
// Process just the specified form
565+
if ($formName) {
566+
if (!isset($this->queue[$formName])) {
567+
$list = implode(', ', array_keys($this->queue));
568+
throw new UndefinedFormException("Form '$formName' was not found. Existing forms: $list");
569+
}
570+
$models[] = $this->createJsModel($this->queue[$formName]);
571+
unset($this->queue[$formName]);
572+
} else { // Or process whole queue
573+
$models = $this->processQueue();
574+
}
575+
// If there are no forms to validate
576+
if (!array_filter($models)) {
577+
return '';
578+
}
535579

536580
$result = array();
537581
foreach ($models as $model) {
538-
$result[] = 'FpJsFormValidator.addModel(' . $model . ');';
582+
$result[] = "FpJsFormValidator.addModel({$model}, {$onLoad});";
539583
}
540584

541-
return '<script type="text/javascript">' . implode("\n", $result) . '</script>';
585+
return implode("\n", $result);
542586
}
543587
}

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ Make sure that your security settings do not prevent these routes.
6161
After the previous steps the javascript validation will be enabled automatically for all your forms.
6262
6363
1. [Disabling validation](Resources/doc/2_1.md)<a name="p_2_1"></a>
64-
2. [Issue with sub-requests](Resources/doc/2_2.md)<a name="p_2_2"></a>
64+
2. [If your forms are placed in sub-requests](Resources/doc/2_2.md)<a name="p_2_2"></a>
65+
3. If you need to initialize JS validation for your forms separately, or by some event, in this case you need to follow [these steps](Resources/doc/2_3.md) instead of the [chapter 1.3](#p_1_3)
6566
6667
## 3 Customization<a name="p_3"></a>
6768

Resources/doc/2_3.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
### 2.3 Custom initialization
2+
3+
So, you have added this part into your template
4+
```twig
5+
<html>
6+
<head>
7+
{{ include('FpJsFormValidatorBundle::javascripts.html.twig') }}
8+
</head>
9+
<body>
10+
11+
</body>
12+
</html>
13+
```
14+
15+
Let's look at what's inside:
16+
```twig
17+
<script src="{{ asset('bundles/fpjsformvalidator/js/fp_js_validator.js') }}" type="text/javascript"></script>
18+
{{ js_validator_config() }}
19+
{{ init_js_validation() }}
20+
```
21+
22+
- the first line loads JS library
23+
- the second one sends some parameters to this library
24+
- the third line - this function processes all the forms which have been added to a queue before, and creates for each one its own JS validation model. So that if you have two or more forms on a page - all of them are processed by this function.
25+
26+
And if you want customize the initialization, you should leave the first and second lines at the header
27+
```twig
28+
<html>
29+
<head>
30+
<script src="{{ asset('bundles/fpjsformvalidator/js/fp_js_validator.js') }}" type="text/javascript"></script>
31+
{{ js_validator_config() }}
32+
</head>
33+
<body>
34+
35+
</body>
36+
</html>
37+
```
38+
and use the third line right at those places where you need it.
39+
40+
This function has three parameters:
41+
```js
42+
init_js_validation(form = null, onLoad = true, wrapped = true)
43+
```
44+
45+
- ```form``` By default this function processes all the forms which are added to the current queue. But if you want process only one specified form - put here a form name or a FormView instance of the necessary form.
46+
For example, you have ```comment``` and ```user``` forms on a page:
47+
```twig
48+
{{ form(comment) }}
49+
init_js_validation(comment)
50+
...
51+
...
52+
{{ form(user) }}
53+
init_js_validation(user)
54+
```
55+
56+
- ```onLoad``` By default JS validation models are initialized on DocumentReady event, but if you need to init it later, on some other event, then you have to disable default behavior:
57+
```twig
58+
{{ form(form) }}
59+
init_js_validation(null, false)
60+
```
61+
- ```wrapper``` this parameter just defines if the result should be wrapped with ```<script type="text/javascript">...</script>``` tag
62+
63+
For example, you need to initialize JS validation only after an ajax request:
64+
```twig
65+
{{ form(user) }}
66+
<script type="text/javascript">
67+
$.ajax({
68+
...
69+
...
70+
complete: function() {
71+
{{ init_js_validation(null, false, false) }}
72+
}
73+
});
74+
</script>
75+
```
76+
- ```null``` means that all the available forms will be initialized
77+
- first ```false``` means that initialization will be performed right at the moment when the 'complete' function is called
78+
- second ```false``` means that JS code will not be wrapped with the 'script' tag

Resources/public/js/FpJsFormValidator.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,12 +347,16 @@ var FpJsFormValidator = new function () {
347347
this.constraintsCounter = 0;
348348

349349
//noinspection JSUnusedGlobalSymbols
350-
this.addModel = function (model) {
350+
this.addModel = function (model, onLoad) {
351351
var self = this;
352352
if (!model) return;
353-
this.onDocumentReady(function () {
353+
if (onLoad !== false) {
354+
this.onDocumentReady(function () {
355+
self.forms[model.id] = self.initModel(model);
356+
});
357+
} else {
354358
self.forms[model.id] = self.initModel(model);
355-
});
359+
}
356360
};
357361

358362
this.onDocumentReady = function (callback) {

Resources/public/js/fp_js_validator.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,12 +347,16 @@ var FpJsFormValidator = new function () {
347347
this.constraintsCounter = 0;
348348

349349
//noinspection JSUnusedGlobalSymbols
350-
this.addModel = function (model) {
350+
this.addModel = function (model, onLoad) {
351351
var self = this;
352352
if (!model) return;
353-
this.onDocumentReady(function () {
353+
if (onLoad !== false) {
354+
this.onDocumentReady(function () {
355+
self.forms[model.id] = self.initModel(model);
356+
});
357+
} else {
354358
self.forms[model.id] = self.initModel(model);
355-
});
359+
}
356360
};
357361

358362
this.onDocumentReady = function (callback) {

Tests/BaseMinkTestCase.php

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,32 +31,59 @@ protected function setUp()
3131
}
3232

3333
/**
34-
* @param string $name
34+
* @param string $path
3535
* @param null $wait
3636
* @param string $submitId
3737
*
3838
* @return array
3939
*/
40-
protected function getAllErrorsOnPage($name, $wait = null, $submitId = 'form_submit')
40+
protected function getAllErrorsOnPage($path, $wait = null, $submitId = 'form_submit')
4141
{
42-
$session = $this->getMink()->getSession('selenium2');
43-
$this->session = $session;
44-
$session->visit($this->base . '/fp_js_form_validator/test/' . $name);
45-
$session->getPage()->findButton($submitId)->click();
42+
$this->visitTest($path);
43+
$this->session->getPage()->findButton($submitId)->click();
4644

4745
if ($wait) {
48-
$session->wait(5000, $wait);
46+
$this->session->wait(5000, $wait);
4947
}
5048

49+
return $this->fetchErrors();
50+
}
51+
52+
protected function fetchErrors()
53+
{
5154
$errorsList = array();
5255
/** @var \Behat\Mink\Element\NodeElement $item */
53-
foreach ($session->getPage()->findAll('css', 'ul.form-errors li') as $item) {
56+
foreach ($this->session->getPage()->findAll('css', 'ul.form-errors li') as $item) {
5457
$errorsList[] = $item->getText();
5558
}
5659

5760
return $errorsList;
5861
}
5962

63+
/**
64+
* Visit a test page
65+
*
66+
* @param $path
67+
*/
68+
protected function visitTest($path)
69+
{
70+
$session = $this->getMink()->getSession('selenium2');
71+
$this->session = $session;
72+
$session->visit($this->base . '/fp_js_form_validator/test/' . $path);
73+
}
74+
75+
/**
76+
* If this was a POST request - we send something to the #extra_msg container
77+
*
78+
* @return bool
79+
*/
80+
protected function wasPostRequest()
81+
{
82+
$extraMsg = $this->session->getPage()->find('css', '#extra_msg')->getText();
83+
84+
return !empty($extraMsg);
85+
}
86+
6087
/**
6188
* @param $selector
6289
*

Tests/BaseTestCase.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Fp\JsFormValidatorBundle\Tests;
44

55
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
6+
use Symfony\Component\DependencyInjection\Container;
67

78
/**
89
* Class BaseTestCase
@@ -28,4 +29,26 @@ protected function callNoPublicMethod($obj, $methodName, array $args = array())
2829

2930
return $method->invokeArgs($obj, $args);
3031
}
32+
33+
/**
34+
* @param $name
35+
*
36+
* @return object
37+
*/
38+
protected function getService($name)
39+
{
40+
return $this->getContainer()->get($name);
41+
}
42+
43+
/**
44+
* @return Container
45+
*/
46+
protected function getContainer()
47+
{
48+
if (!self::$kernel) {
49+
self::bootKernel();
50+
}
51+
52+
return self::$kernel->getContainer();
53+
}
3154
}

0 commit comments

Comments
 (0)