Sébastien Grans
Sébastien Grans

Reputation: 41

Tags Textext Jquery plugin, a good way to save created tags with symfony 2?

i work with symfony2 and now i try to save in a entity or directly in the database, the tags created in the texarea input of the tag textext Jquery plug-in. I don't know the good way to persist values (noted that in the future i want to use Filter with Suggestions functionality of the plug-in).

I think to this method:

Here a extract of my oeuvre mapping entity where i want to save the value.

/**
 * @ORM\ManyToMany(targetEntity="tagz",cascade={"persist"})
 * @ORM\JoinTable(name="oeuvre_tagz",
 *     joinColumns={@ORM\JoinColumn(name="oeuvre_id", referencedColumnName="id",     nullable=false)},
 *     inverseJoinColumns={@ORM\JoinColumn(name="tagz_id", referencedColumnName="id", nullable=false)})
 **/
private $tagz;

In my formtype:

public function buildForm(FormBuilderInterface $builder, array $options)
{

switch ($options['flowStep']) {
...
case 5:
        $builder->add('tagz', 'textarea', array(
            'mapped' => false,
            'required'=>false,
        ));
        break;

My view, i use a multistep form, craue bundle:

{% if flow.getCurrentStep() == 5 %}
    <script type="text/javascript">
        $().ready(function () {
            $('#axxon_musicbundle_oeuvretype_tagz').textext({ plugins: 'tags' });
            $('#form').submit(function() {
 $('form').get(0).setAttribute('action', '{{ path("axxon_music_ExtractFormTagz") }}');
                    var tagz = Array;
                        tagz =$('input[name*="axxon_musicbundle_oeuvretype[tagz]"]').val();
                            var actionController =$("#form").attr("action");
                            $.ajax({
                                type: 'POST',
                                data: {'tagz': tagz},
                                url: actionController,
                                success: function () {
                                    $('form').get(0).setAttribute('action', '{{ path("axxon_music_add_oeuvre") }}');

               ... is this a good choice to do like that ?

                        });
                    });
    </script>
    <fieldset>
        <legend>Etape {{ flow.getCurrentStep() }} / {{ flow.getMaxSteps() }}, Ajouter des mots clefs descriptifs
        </legend>
        <ul>
            <li>
                {{ form_row(form.tagz) }}
            </li>

        </ul>
        {% include 'CraueFormFlowBundle:FormFlow:buttons.html.twig' %}
    </fieldset>

{% endif %}

My controller where i want receiving data:

    public function ExtractFormTagzAction(){


    if ($this->getRequest()->isXmlHttpRequest()) {

        $tagz = $this->getRequest()->request->get('tagz');
    }

Many thanks.

Upvotes: 1

Views: 941

Answers (1)

Zeljko
Zeljko

Reputation: 5158

This is wrong way to do it, it can be much simpler and very reusable.

In your Form, instead of

    $builder->add('tagz', 'textarea', array(
        'mapped' => false,
        'required'=>false,
    ));

you should have

    $builder->add('tagz', 'tag_text', .... ));

Then you need to build new form type, let's call it TagTextType. It's parent would be "textarea" and name "tag_text". In form templates, you have to make

{% block tag_text_widget %}....{% endblock %}

in which you will put required javascript.

Now here comes the tricky part: in that TagTextType, you have to addTransformer that will convert existing tags into string, or explode text into array of tags. The topic is too big for me to write it here, you have really good documentation on Symfony site.

As an example for you, check my widget. I am using some other plugin, but you will get an idea:

{% block jquerytexttags_widget %}

    {{ form_widget(form) }} 

    <script type="text/javascript">
        $("#{{ id }}").textntags( {
            triggers: {'@': { uniqueTags : false } } ,
            onDataRequest: function (mode, query, triggerChar, callback) {
                var data = {{ availableUsers|raw }} ;
                query = query.toLowerCase();
                var found = _.filter(data, function(item) { return item.name.toLowerCase().indexOf(query) > -1; });
                callback.call(this, found);
            }
        } );
    </script>
{% endblock %}

It can be tricky to start but once you build it, you will be able to use it anywhere you want. Imagine big, nested forms that will still be rendered properly with just one line

{{ form_widget(form) }}

Cool, isn't it? :)

Upvotes: 1

Related Questions