To implement your own form fields, you need to have a thorough understanding of the data flow within a form field. A form field stores its data in three different representations: (1) the format required by the form's object (2) a normalized format for internal processing (3) the format used for display A date field, for example, may store a date as "Y-m-d" string (1) in the object. To facilitate processing in the field, this value is normalized to a DateTime object (2). In the HTML representation of your form, a localized string (3) is presented to and modified by the user. In most cases, format (1) and format (2) will be the same. For example, a checkbox field uses a Boolean value both for internal processing as for storage in the object. In these cases you simply need to set a value transformer to convert between formats (2) and (3). You can do this by calling setValueTransformer() in the configure() method. In some cases though it makes sense to make format (1) configurable. To demonstrate this, let's extend our above date field to store the value either as "Y-m-d" string or as timestamp. Internally we still want to use a DateTime object for processing. To convert the data from string/integer to DateTime you can set a normalization transformer by calling setNormalizationTransformer() in configure(). The normalized data is then converted to the displayed data as described before.
Author: Bernhard Schussek (bernhard.schussek@symfony-project.com)
Inheritance: extends Symfony\Component\Form\Configurable, implements Symfony\Component\Form\FieldInterface
 /**
  * {@inheritDoc}
  */
 public function bind($data)
 {
     if ($this->mode === self::GROUP) {
         parent::bind($data);
     } else {
         Field::bind($data);
     }
 }
 /**
  * {@inheritDoc}
  */
 protected function configure()
 {
     // default precision is locale specific (usually around 3)
     $this->addOption('precision');
     $this->addOption('grouping', false);
     $this->addOption('rounding-mode', NumberToLocalizedStringTransformer::ROUND_HALFUP);
     parent::configure();
     $this->setValueTransformer(new NumberToLocalizedStringTransformer(array('precision' => $this->getOption('precision'), 'grouping' => $this->getOption('grouping'), 'rounding-mode' => $this->getOption('rounding-mode'))));
 }
 /**
  * {@inheritDoc}
  */
 protected function configure()
 {
     $this->addOption('value');
     parent::configure();
     $this->setValueTransformer(new BooleanToStringTransformer());
 }
Exemple #4
0
 /**
  * {@inheritDoc}
  */
 public function writeProperty(&$objectOrArray)
 {
     $isReference = false;
     // If the data is identical to the value in $objectOrArray, we are
     // dealing with a reference
     if ($this->getPropertyPath() !== null) {
         $isReference = $this->getData() === $this->getPropertyPath()->getValue($objectOrArray);
     }
     // Don't write into $objectOrArray if $objectOrArray is an object,
     // $isReference is true (see above) and the option "by_reference" is
     // true as well
     if (!is_object($objectOrArray) || !$isReference || !$this->getOption('by_reference')) {
         parent::writeProperty($objectOrArray);
     }
 }
Exemple #5
0
 /**
  * {@inheritDoc}
  */
 public function isEmpty()
 {
     if ($this->mode === self::FORM) {
         return parent::isEmpty();
     }
     return Field::isEmpty();
 }
Exemple #6
0
 /**
  * {@inheritDoc}
  */
 public function addError(FieldError $error, PropertyPathIterator $pathIterator = null, $type = null)
 {
     if (null !== $pathIterator) {
         if ($type === self::FIELD_ERROR && $pathIterator->hasNext()) {
             $pathIterator->next();
             if ($pathIterator->isProperty() && $pathIterator->current() === 'fields') {
                 $pathIterator->next();
             }
             if ($this->has($pathIterator->current()) && !$this->get($pathIterator->current())->isHidden()) {
                 $this->get($pathIterator->current())->addError($error, $pathIterator, $type);
                 return;
             }
         } else {
             if ($type === self::DATA_ERROR) {
                 $iterator = new RecursiveFieldIterator($this);
                 $iterator = new \RecursiveIteratorIterator($iterator);
                 foreach ($iterator as $field) {
                     if (null !== ($fieldPath = $field->getPropertyPath())) {
                         if ($fieldPath->getElement(0) === $pathIterator->current() && !$field->isHidden()) {
                             if ($pathIterator->hasNext()) {
                                 $pathIterator->next();
                             }
                             $field->addError($error, $pathIterator, $type);
                             return;
                         }
                     }
                 }
             }
         }
     }
     parent::addError($error);
 }
 /**
  * {@inheritDoc}
  */
 public function submit($data)
 {
     if ($this->mode === self::FORM) {
         parent::submit($data);
     } else {
         Field::submit($data);
     }
 }
 /**
  * Sets the locale of this field.
  *
  * @see Localizable
  */
 public function setLocale($locale)
 {
     parent::setLocale($locale);
     foreach ($this->fields as $field) {
         $field->setLocale($locale);
     }
 }
 protected function configure()
 {
     $this->addOption('foo');
     $this->addRequiredOption('bar');
     parent::configure();
 }
 /**
  * Expose method for testing purposes
  */
 public function getNormalizedData()
 {
     return parent::getNormalizedData();
 }
 /**
  * {@inheritDoc}
  */
 public function getAttributes()
 {
     return array_merge(parent::getAttributes(), array('type' => 'text/javascript', 'src' => $this->_src));
 }
Exemple #12
0
 /**
  * {@inheritDoc}
  */
 public function writeProperty(&$objectOrArray)
 {
     $data = $this->getData();
     // Don't update parent if data is a composite type (object or array)
     // and "by_reference" option is true, because then we expect that
     // we are working with a reference to the parent's data
     if (!(is_object($data) || is_array($data)) || !$this->getOption('by_reference')) {
         parent::writeProperty($objectOrArray);
     }
 }
 /**
  * Distributes the generator among all nested fields
  *
  * @param HtmlGeneratorInterface $generator
  */
 public function setGenerator(HtmlGeneratorInterface $generator)
 {
     parent::setGenerator($generator);
     // TESTME
     foreach ($this->fields as $field) {
         $field->setGenerator($generator);
     }
 }