programing

Symfony 2 양식에서 데이터 프로토 타입 속성을 사용자 정의하는 방법

copysource 2021. 1. 16. 20:38
반응형

Symfony 2 양식에서 데이터 프로토 타입 속성을 사용자 정의하는 방법


수십 일 이후로 나는 Symfony 2 및 양식의 문제를 차단합니다.

나는 웹 사이트 엔티티의 한 형태를 얻었다. "웹 사이트"는 웹 사이트의 엔티티 모음이며 각 웹 사이트에는 "유형"과 "URL"이라는 두 가지 속성이 있습니다.

데이터베이스에 하나의 웹 사이트를 더 추가하려면 "다른 웹 사이트 추가"링크를 클릭하여 양식에 다른 웹 사이트 행을 추가합니다. 따라서 제출 버튼을 클릭하면 하나 또는 X 개의 웹 사이트를 동시에 추가 할 수 있습니다.

행을 추가하는이 프로세스는 웹 사이트 하위 양식을 생성 할 수있는 data-prototype 속성을 사용합니다.

문제는 훌륭한 그래픽 렌더링을 갖도록 양식을 사용자 정의한다는 것입니다.

<div class="informations_widget">{{ form_widget(website.type.code) }}</div>
<div class="informations_error">{{ form_errors(website.type) }}</div>
<div class="informations_widget">{{ form_widget(website.url) }}</div>
<div class="informations_error">{{ form_errors(website.url) }}</div>

그러나 데이터 프로토 타입은 HTML 및 CSS 태그 및 속성을 사용하여 이러한 사용자 정의에 관심이 없습니다. 나는 Symfony 렌더링을 유지합니다.

<div>
<label class=" required">$$name$$</label>
<div id="jobcast_profilebundle_websitestype_websites_$$name$$">
<div>
<label class=" required">Type</label>
<div id="jobcast_profilebundle_websitestype_websites_$$name$$_type">
<div>
<label for="jobcast_profilebundle_websitestype_websites_$$name$$_type_code" class=" required">label</label>
<select id="jobcast_profilebundle_websitestype_websites_$$name$$_type_code" name="jobcast_profilebundle_websitestype[websites][$$name$$][type][code]" required="required">
<option value="WEB-OTHER">Autre</option>
<option value="WEB-RSS">Flux RSS</option>
...
</select>
</div>
</div>
</div>
<div>
<label for="jobcast_profilebundle_websitestype_websites_$$name$$_url" class=" required">Adresse</label>
<input  type="url" id="jobcast_profilebundle_websitestype_websites_$$name$$_url" name="jobcast_profilebundle_websitestype[websites][$$name$$][url]" required="required" value="" />
</div>
</div>
</div>

누구든지 그 해킹을 할 아이디어가 있습니까?


조금 오래되었지만 여기에 치명적인 간단한 해결책이 있습니다.

아이디어는 단순히 Twig 템플릿을 통해 컬렉션 항목을 렌더링하는 것이므로 data-prototype="..."태그에 배치 할 프로토 타입을 완전히 사용자 지정할 수 있습니다 . 마치 평범하고 평범한 형태 인 것처럼.

yourMainForm.html.twig에서 :

<div id="collectionContainer"
     data-prototype="
         {% filter escape %}
             {{ include('MyBundle:MyViewsDirectory:prototype.html.twig', { 'form': form.myForm.vars.prototype }) }}
         {% endfilter %}">
</div>

그리고 MyBundle : MyViewsDirectory : prototype.html.twig에서 :

<div>
    <!-- customize as you wish -->
    {{ form_label(form.field1) }}
    {{ form_widget(form.field1) }}
    {{ form_label(form.field2) }}
    {{ form_widget(form.field2) }}
</div>

크레딧 : https://gist.github.com/tobalgists/4032213 에서 수정 됨


나는이 질문이 꽤 오래되었다는 것을 알고 있지만 나는 같은 문제를 가지고 있었고 이것이 내가 그것을 뿌린 방법입니다. 나는 macro이것을 달성하기 위해 나뭇 가지 를 사용하고있다. 매크로는 함수와 같으며 다른 인수로 렌더링 할 수 있습니다.

{% macro information_prototype(website) %}
    <div class="informations_widget">{{ form_widget(website.type.code) }}</div>
    <div class="informations_error">{{ form_errors(website.type) }}</div>
    <div class="informations_widget">{{ form_widget(website.url) }}</div>
    <div class="informations_error">{{ form_errors(website.url) }}</div>
{% endmacro %}

이제 원하는 곳에이 매크로를 렌더링 할 수 있습니다. information_prototype()매크로의 이름 만입니다, 당신은 당신이 원하는대로 그 이름을 지정할 수 있습니다. 매크로를 사용하여 주어진 항목과 프로토 타입을 같은 방식으로 렌더링하려면 다음과 같이하십시오.

<div class="collection" data-prototype="{{ _self.information_prototype(form.websites.vars.prototype)|e }}">
    {% for website in form.websites %}
        {{ _self.information_prototype(website) }}
    {% endfor %}
    <button class="add-collection">Add Information</button>
</div>

form.websites.vars.prototypeprototype_name지정한 양식의 프로토 타입 데이터를 보유 합니다. 사용 _self.+macroname같은 템플릿에 매크로를 사용하려는 경우.

Twig 문서 에서 매크로에 대해 자세히 알아볼 수 있습니다.


당신은 아마 그 이후로 알았을 것입니다. 그러나 여기에 다른 사람들을위한 해결책이 있습니다.

새 템플릿을 만들고 여기에 다음 코드를 복사 / 붙여 넣기 : https://gist.github.com/1294186

그런 다음 사용자 지정하려는 양식이 포함 된 템플릿에서 다음을 수행하여 양식에 적용합니다.

{% form_theme form 'YourBundle:Deal:Theme/_field-prototype.html.twig' %}

최근 비슷한 문제가 발생했습니다. 다음은 html에서 명시 적으로 설정하지 않고도 컬렉션 프로토 타입을 재정의하는 방법입니다.

{% set customPrototype %}
    {% filter escape %}
        {% include 'AcmeBundle:Controller:customCollectionPrototype.html.twig' with { 'form': form.collection.vars.prototype } %}
    {% endfilter %}
{% endset %}
{{ form_label(form.collection) }}
{{ form_widget(form.collection, { 'attr': { 'data-prototype': customPrototype } }) }}

사용자 지정 나뭇 가지에서 원하는대로 할 수 있습니다. 예를 들면 :

<div data-form-collection="item" data-form-collection-index="__name__" class="collection-item">
<div class="collection-box col-sm-10 col-sm-offset-2 padding-top-20">
    <div class="row form-horizontal form-group">
        <div class="col-sm-4">
            {{ form_label(form.field0) }}
            {{ form_widget(form.field0) }}
        </div>
        <div class="col-sm-3">
            {{ form_label(form.field1) }}
            {{ form_widget(form.field1) }}
        </div>
        <label class="col-sm-3 control-label text-right">
            <button data-form-collection="delete" class="btn btn-danger">
                <i class="fa fa-times collection-button-remove"></i>{{ 'form.collection.delete'|trans }}
            </button>
        </label>
    </div>
</div>

특정 위치에서만 수행해야하고 모든 컬렉션에 적용되는 전역 재정의가 필요하지 않을 때 유용합니다.


답변이 매우 늦었지만 방문자에게 유용 할 수 있습니다.

테마 파일에서 다음과 같이 웹 사이트 위젯의 모든 컬렉션 항목을 렌더링하는 데 하나의 블록을 사용할 수 있습니다.

{% block _jobcast_profilebundle_websitestype_websites_entry_widget %}
     <div class="informations_widget">{{ form_widget(form.type.code) }}</div>
     <div class="informations_error">{{ form_errors(form.type) }}</div>
     <div class="informations_widget">{{ form_widget(form.url) }}</div>
     <div class="informations_error">{{ form_errors(form.url) }}</div>
{% endblock %}

또한 다음과 같이 컬렉션 위젯 행에 대한 테마 블록을 만듭니다.

{% block _quiz_question_answers_row %}
     {% if prototype is defined %}
        {%- set attr = attr | merge({'data-prototype': form_row(prototype) }) -%}
    {% endif %}

     {{ form_errors(form) }}

     {% for child in form %}
         {{ form_row(child) }}
     {% endfor %}
{% endblock %}

이제 프로토 타입과 렌더링 된 컬렉션 항목이 동일합니다.


비슷한 문제가있었습니다. 귀하의 사례를 위해 작동하도록 이것을 조정해야 할 수도 있지만 누군가가 도움이 될 수 있습니다.

사용자 지정 양식 '테마'를 보관할 새 템플릿 파일을 만듭니다.

./src/Company/TestBundle/Resources/views/Forms/fields.html.twig

일반적으로 form_row 함수를 사용하여 필드의 레이블, 오류 및 위젯을 표시 할 수 있습니다 . 하지만 제 경우에는 위젯을 표시하고 싶었습니다. 말했듯이 데이터 프로토 타입 기능을 사용하면 레이블도 표시되므로 새 fields.html.twig에 원하는 필드 모양에 대한 사용자 정의 코드를 입력합니다.

{% block form_row %}
{% spaceless %}
        {{ form_widget(form) }}
{% endspaceless %}
{% endblock form_row %}

컨테이너 div, 레이블 및 오류를 제거하고 위젯을 그대로 두었습니다.

이제 양식을 표시하는 twig 파일에서 {% extends ... %} 뒤에 이것을 추가하면됩니다.

{% form_theme form 'CompanyTestBundle:Form:fields.html.twig' %}

이제 form_widget (form.yourVariable.var.prototype)은 필드 만 렌더링하고 다른 것은 렌더링하지 않습니다.


응용 프로그램 전체 양식 테마가 프로토 타입에 적용됩니다. 응용 프로그램 전체 사용자 지정을 참조하십시오.


다음은 사용자 지정 데이터 프로토 타입의 샘플 코드입니다.

{{ form_widget(form.emails.get('prototype')) | e }}

어디 emails-컬렉션.


To customize differently existing collection items VS prototype, you can override collection_widget like this:

{%- block collection_widget -%}
    {% if prototype is defined %}
        {%- set attr = attr|merge({'data-prototype': form_row(prototype, {'inPrototype': true} ) }) -%}
    {% endif %}
    {{- block('form_widget') -}}
{%- endblock collection_widget -%}

And then in your custom entry:

{% block _myCollection_entry_row %}

  {% if(inPrototype is defined) %}
      {# Something special only for prototype here #}
  {% endif %}
{% endblock %}

If you do not need to define a template system-wide, simply set a template in your twig template, and ask twig to use it.

{# using the profiler, you can find the block widget tested by twig #}
{% block my_block_widget %}
    <div >
      <p>My template for collection</p>
        <div >
          {{ form_row(form.field1)}}
        </div>
        <div>
          {{ form_row(form.field2)}}
        </div>
    </div>
{% endblock %}

{% form_theme form.my_collection _self %}

<button data-form-prototype="{{ form_widget(form.my_collection.vars.prototype) )|e }}" >Add a new entry</button>

This post focuses on using pre-existing conventions within the twig template.

Basing off "How to Embed a Collection of Forms" from the Symfony Cookbook (http://symfony.com/doc/master/cookbook/form/form_collections.html), you can just enter whatever html_escaped form data you wish in the data-prototype (maybe considered a hack, but works wonderfully) and only pages using that template will change.

In the example, they tell you to put:

    <ul class="tags" data-prototype="{{ form_widget(form.tags.vars.prototype)|e }}">
    ...
    </ul>

This can be successfully replaced with something such as:

<table class="tags" data-prototype="&lt;tr&gt;  &lt;td&gt;&lt;div&gt;&lt;input type=&quot;text&quot; id=&quot;task_tags__name__tagId&quot; name=&quot;task[tags][__name__][taskId]&quot; disabled=&quot;disabled&quot; required=&quot;required&quot;    size=&quot;10&quot; value=&quot;&quot; /&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div&gt;&lt;input type=&quot;text&quot; id=&quot;task_tags__name__tagName&quot; name=&quot;task[tags[__name__][tagName]&quot; required=&quot;required&quot; value=&quot;&quot; /&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;">
    <tr>
        <th>Id</th>
        <th>Name</th>
    </tr>
    <tr>
    ...pre existing data here...
    </tr>
</table>    

Where the data-type attribute of the table with the class "tags" above is the html-escaped version (and line breaks removed though spaces are ok and required) of:

<tr>
    <td><div><input type="text" id="task_tags__name__tagId" name="task[tags][__name__][taskId]" disabled="disabled" required="required"    size="10" value="" /></div></td>
    <td><div><input type="text" id="task_tags__name__tagName" name="task[tags[__name__][tagName]" required="required" value="" /></div></td>
</tr>

...but you must also adjust the javascript in the example to add tr's instead of li elements:

function addTagForm(collectionHolder, $newLinkTr) {
    ...
    // Display the form in the page in an tr, before the "Add a question" link tr
    var $newFormTr = $('<tr></tr>').append(newForm);
    ...
};

...

// setup an "add a tag" link
var $addTagLink = $('<a href="#" class="add_tag_link">Add a tag</a>');
var $newLinkTr = $('<tr></tr>').append($addTagLink);

...

For me, the next step is figuring out how to define the prototype in an external file that I can somehow call in the twig template for the data-prototype that dynamically works with the form. Something like:

<table class="tags" data-prototype="{{somefunction('App\Bundle\Views\Entity\TagsPrototypeInTable')}}">

So if one of the other posts is describing this and I am too dense or if someone knows how to do such, say so!

There is a link to something from gitHub from Francois, but I didn't see any explanation so I think that is probably the more dynamic method I'll get to one of these near-future days.

Peace, Steve

Update:

One can also use just parts of the prototype:

data-prototype="&lt;tr&gt;  &lt;td&gt;{{ form_row(form.tags.vars.prototype.tagId) | e }}&lt;/td&gt; &lt;td&gt;{{ form_row(form.tags.vars.prototype.tagName) | e }}&lt;/td&gt;&lt;/tr&gt;"

Where the data-type attribute of the table with the class "tags" above is the html-escaped version (and line breaks removed though spaces are ok and required) of:

<td>{{ form_row(form.tags.vars.prototype.tagId) | e }}</td>
<td>{{ form_row(form.tags.vars.prototype.tagName) | e }}</td>

(I used http://www.htmlescape.net/htmlescape_tool.html.)

Symfony will replace the information between the {{}} with an html_escaped (because of the "|e") rendered field when the page is rendered. In this way, any customization at the field-level is not lost, but! you must manually add and remove fields to the prototype as you do so with the entity :)

ReferenceURL : https://stackoverflow.com/questions/7555702/how-to-customize-the-data-prototype-attribute-in-symfony-2-forms

반응형