2012-03-26 8 views
2

Ich bekomme einige Probleme zu verstehen, wie Symfony2 benutzerdefinierte Formularfeldtypen arbeiten. Ich muss einen neuen Typ mit einigen benutzerdefinierten Attributen erstellen (HTML5 data-*) basierend auf Daten, die an MyType übergeben werden.Benutzerdefiniertes Formularfeld in Symfony2, unerwünschtes Attribut geerbt

Das Problem ist, dassMyType zu der Hauptform nach der Zugabe, die das Etikett data-* Attribut erbt.

// Add MyType to the main form 

$builder->add('somename', new MyType(), array('label' => 'my label')); 

Dies ist meine individuelle Art:

class MyType extends AbstractType 
{ 

    public function getDefaultOptions(array $options) 
    { 
     $source = isset($option['source']) ? json_encode($option['source']) : ''; 

     return array(
      'attr' => array(
       'data-source' => $source 
      ) 
     ); 
    } 

    public function getName() { return 'mytype'; } 

    public function getParent(array $options) { return 'text'; } 

} 
+0

Nur zur Bestätigung sagen Sie, dass Ihre Label-HTML-Entität beim Rendern mit einem Datenquellenattribut endet? Wenn ja, dann kann ich dabei helfen. Wenn es etwas anderes ist, dann vielleicht auch nicht. – Cerad

+0

@Cerad ja, Label hat genau die gleichen Attribute wie das Widget. – gremo

Antwort

1

EDIT: soweit ich array('attr' => array('myattr1' => 'value1')) als Option vorbei für den Bauherrn verstehen kann als gemeinsames Attribut für den Bauherrn bestimmt ist und alle seine untergeordneten Elemente . Dies ist der Grund, warum zum Beispiel die Übergabe der array('required' => false)Formularebene die HTML5-integrierte clientseitige Validierung für jedes Feld innerhalb dieses Formulars deaktiviert.

(Immer auf der Suche nach einer besseren Lösung) ich meinen Weg durch diese blog post inspiriert veröffentlichen werde,: ein benutzerdefinierte Formularfeld mit Ansicht und einen Zweig Block erstellen neue Attribute Attribute.

class TypeheadType extends AbstractType 
{ 

    public function buildForm(FormBuilder $builder, array $options) 
    { 
     $builder 
      ->setAttribute('mode', $options['mode']) 
      ->setAttribute('items', $options['items']); 

    } 

    public function buildView(FormView $view, FormInterface $form) 
    { 

     $view 
      ->set('mode', $form->getAttribute('mode')) 
      ->set('items', $form->getAttribute('items')); 
    } 

    public function getDefaultOptions(array $options) 
    { 

     return array(
      'mode' => 'single', 
      'items' => 10 
     ); 
    } 

    public function getName() { return 'typehead'; } 

    public function getParent(array $options) { return 'field'; } 

} 

Der neue Formulartyp als Dienst registrieren werden sollte und Alias ​​übereinstimmen, was durch getName() zurückgegeben wird (das ist obligatorisch? Keine Ahnung ...):

form.type.typehead: 
    class: Acme\HelloBundle\Form\Type\TypeheadType 
    tags: 
    - { name: form.type, alias: typehead } 

Neue Felderstellung (anderswo):

$builder->add('myfield', 'typehead', array('items' => 15)); 

In Zweig Form Thema Widget Block (Muster für Name ist as getName() . '_widget) Sie Ansichtsattribute setted in TypeheadType verwenden können:

{% block typehead_widget %} 
{% spaceless %} 
    <input type="text" {{ block('widget_attributes') }} 
     {% if value is not empty %}value="{{ value }}" {% endif %} 
     data-items="{{ items }}" data-mode="{{ mode }}" /> 
{% endspaceless %} 
{% endblock typehead_widget %} 

Und schließlich:

{{ form_row(form.myfield) }} 
1

So das Grundproblem ist, dass Etikett die Attribute alle auf das Widget aufgreift. Ich verstehe wirklich nicht, warum sie es so gestaltet, aber wenn man sich anschaut:

{# Symfony/Bridge/Twig/Resources/Form/form_div_layout.html.twig #} 
{% block generic_label %} 
{% spaceless %} 
    {% if required %} 
     {% set attr = attr|merge({'class': attr.class|default('') ~ ' required'}) %} 
    {% endif %} 
    <label{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor%}>{{ label|trans }}</label> 
{% endspaceless %} 
{% endblock %} 

können Sie sehen, dass generic_label (standardmäßig genannt) Dumps aus jedes Attribut.

overrode ich den Standard mit:

{% block generic_label %} 
{% spaceless %} 
    {% if required %} 
     {% set attr = attr|merge({'class': attr.class|default('') ~ ' required'}) %} 
    {% endif %} 
    <label {{ block('label_attributes') }}>{{ label|trans }}</label> 
{% endspaceless %} 
{% endblock %} 

{% block label_attributes %} 
{% spaceless %} 
    {% for attrname,attrvalue in attr %}{% if (attrname == 'for' or attrname == 'class') %} {{attrname}}="{{attrvalue}}"{% endif %}{% endfor %} 
{% endspaceless %} 
{% endblock %} 

Mein label_attributes nur für setzt heraus blockieren und Klasse Attribute, die alles, was ich bisher gebraucht. Auch hier ist die Standardimplementierung verwirrend und ich vermisse wahrscheinlich etwas Offensichtliches, aber die Überschreibung scheint in Ordnung zu sein. Verwenden Sie die form_theme in der neuen Formen Datei zu bringen:

{% form_theme form 'ZaysoCoreBundle:Layout:fields.html.twig' %} 
+0

Upvote für die Zweiglösung, danke. Aber ich habe einen besseren gefunden und werde es so bald wie möglich posten. – gremo

+0

Wir freuen uns auf die alternative Lösung. Meine Lösung funktioniert, aber wie gesagt, hatte ich immer das Gefühl, etwas Offensichtliches zu vermissen. – Cerad

+0

Antwort geschrieben, lass mich wissen, was denkst du darüber. Vielen Dank. – gremo