Burgov / KeyValueFormBundle

A form type for managing key-value pairs
MIT License
44 stars 32 forks source link

Can't get it working #9

Closed robhunt3r closed 9 years ago

robhunt3r commented 9 years ago

I cloned the extraProperties field for my own content, and using it like this

            ->add('extraProperties', 'burgov_key_value', array(
                'label' => 'form.label_extraProperties',
                'value_type' => 'text',
                'use_container_object' => true,
            ))

But it doesn't show anything, just the label.

Here are my classes

interface GameModelInterface {

    /**
     * @param array|\Traversable|KeyValueContainer
     */
    public function setExtraProperties($extraProperties);
    /**
     * @return array
     */
    public function getExtraProperties();
    /**
     * Add a key-value pair for meta attribute property.
     *
     * @param string $key
     * @param string $value
     */
    public function addExtraProperty($key, $value);
}
class GameModel implements GameModelInterface {

    /**
     * To store meta tags for type property.
     *
     * @var array
     */
    private $extraProperties = array();

    /**
     * {@inheritDoc}
     */
    public function setExtraProperties($extraProperties)
    {
        $this->extraProperties = $this->toArray($extraProperties);

        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public function getExtraProperties()
    {
        return $this->extraProperties;
    }

    /**
     * {@inheritDoc}
     */
    public function addExtraProperty($key, $value)
    {
        $this->extraProperties[$key] = (string) $value;
    }

    /**
     * {@inheritDoc}
     */
    public function removeExtraProperty($key)
    {
        if (array_key_exists($key, $this->extraProperties)) {
            unset($this->extraProperties[$key]);
        }
    }
    /**
     * Extract an array out of $data or throw an exception if not possible.
     *
     * @param array|KeyValueContainer|\Traversable $data Something that can be converted to an array.
     *
     * @return array Native array representation of $data
     *
     * @throws InvalidArgumentException If $data can not be converted to an array.
     */
    private function toArray($data)
    {
        if (is_array($data)) {
            return $data;
        }

        if ($data instanceof KeyValueContainer) {
            return $data->toArray();
        }

        if ($data instanceof \Traversable) {
            return iterator_to_array($data);
        }

        throw new InvalidArgumentException(sprintf('Expected array, Traversable or KeyValueContainer, got "%s"', is_object($data) ? getclass($data) : get_type($data)));
    }
} 
class GameContent extends stc implements GameModelInterface {
    /**
     * @var string
     */
    protected $app;

    /**
     * To store meta tags for type property.
     *
     * @var array
     */
    private $extraProperties = array();

    /**
     * {@inheritDoc}
     */
    public function setExtraProperties($extraProperties)
    {
        $this->extraProperties = $this->toArray($extraProperties);

        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public function getExtraProperties()
    {
        return $this->extraProperties;
    }

    /**
     * {@inheritDoc}
     */
    public function addExtraProperty($key, $value)
    {
        $this->extraProperties[$key] = (string) $value;
    }

    /**
     * {@inheritDoc}
     */
    public function removeExtraProperty($key)
    {
        if (array_key_exists($key, $this->extraProperties)) {
            unset($this->extraProperties[$key]);
        }
    }
(... more content)

It works if I use collectionType and using allowadd and allowremove, but it shows only one field (and I want a key=> value field)

hacfi commented 9 years ago

@robhunt3r Afaik if extraProperties is empty this form type won’t show anything.

robhunt3r commented 9 years ago

@hacfi So I would need to initialize it right? Like this way it's initialized but isn't showing any + or - button to add/remove pairs. How can I achieve that?

    public function getNewInstance()
    {
        $instance = parent::getNewInstance();
        $instance->setExtraProperties(array("KEY"=>"VALUE"));

        return $instance;
    }

captura de pantalla 2014-10-07 a la s 18 45 40

hacfi commented 9 years ago

@robhunt3r I don’t know..that’s not part of this bundle afaik. Maybe someone else knows better how to achieve this nicely (I would use form collections for that).

robhunt3r commented 9 years ago

@hacfi Well I thought this would be the bundle :P because as far as I've read, in order to set a key=>value pair form field to a PHPCR element (a StaticContent in this case) we have to use it...

Using form collections I can't make a key=>value field, when I say I can't I mean I don't know how, I've searched but nothing was what I wanted... only embedded collections and that...

hacfi commented 9 years ago

I think this bundle only provides the functionality to edit arrays and by that I mean editting the values of predefined keys and not dynamically adding more key/value pairs. But @Burgov or @dbu know better what it actually does..I’ve only used it once.

robhunt3r commented 9 years ago

Maybe I misunderstood the functionality of the bundle then :P

dbu commented 9 years ago

No, that is the idea. See how its used in https://github.com/symfony-cmf/SeoBundle/blob/master/Form/Type/SeoMetadataType.php - on clicking the + button, you should get two fields, one for the key and one for the value. If the data already has a non-empty hashmap, those are displayed too. Did you read http://symfony.com/doc/current/cookbook/form/form_collections.html#allowing-new-tags-with-the-prototype ?

We use that form type inside sonata admin, so maybe you need to run some javascript to make it work?

@Burgov would you happen to know that?

robhunt3r commented 9 years ago

@dbu Yeah I've read the books and also saw how it works on SeoBundle, that's why I used part of the code (using this bundle, and adding the extrapreferences field to my own content the same way SeoBundle does) but didn't saw the buttons, I thought this bundle would autorun the javascript stuff that's why I was expecting to get it out of the box. I will try to use custom javascript in order to get it working then.

dbu commented 9 years ago

afaik this bundle does no javascript on its own, like symfony forms itself also does not. otherwise it would tie you to one javascript framework or make you run two frameworks, which would both be a problem.

robhunt3r commented 9 years ago

I've researched and found that even when SonataAdmin automaticaly creates the buttons for a collection type form, it doesn't do on forms created with this bundle.

Inside code I've found this concret piece

{% block widget_container_attributes_choice_widget %}
    {% spaceless %}
        id="{{ id }}"
        {% for attrname,attrvalue in attr %}{{attrname}}="{% if attrname == 'class' %}list-unstyled {% endif%}{{attrvalue}}" {% endfor %}
        {% if "class" not in attr %}class="list-unstyled"{%endif %}
    {% endspaceless %}
{% endblock %}

When using this bundle, this code is not launching, Sonata treats this new form type like a normal type, not collection so it isn't adding the "add new" button, and then of course it won't append anything.

Here you can see it working with the same sonata code http://jsfiddle.net/robhunter/ct3xwntp/

I will check further in order to create a PR which allows this bundle co-work with sonata out of the box, as I've tested with SonataBundle and it doesn't add the buttons either.

robhunt3r commented 9 years ago

Okay found it. Adding this inside SonataAdminBundle:Form:form_admin_fields.html.twig

{% block burgov_key_value_widget %}
    {{- block('sonata_type_native_collection_widget') -}}
{% endblock %}

Adds the buttons correctly and working for key=>value pair and persisting :)

dbu commented 9 years ago

Is the readme incomplete? Or could it be improved to make it harder to overlook this bit?

----- Reply message ----- Von: "Rob Hunter" notifications@github.com An: "Burgov/KeyValueFormBundle" KeyValueFormBundle@noreply.github.com Cc: "David Buchmann" david@liip.ch Betreff: [KeyValueFormBundle] Can't get it working (#9) Datum: Di., Okt. 7, 2014 23:59 Okay found it. Adding this inside SonataAdminBundle:Form:form_admin_fields.html.twig

{% block burgov_key_value_widget %} {{- block('sonata_type_native_collection_widget') -}} {% endblock %}

Adds the buttons correctly and working for key=>value pair and persisting :)

— Reply to this email directly or view it on GitHub. {"@context":"http://schema.org","@type":"EmailMessage","description":"View this Issue on GitHub","action":{"@type":"ViewAction","url":"https://github.com/Burgov/KeyValueFormBundle/issues/9#issuecomment-58270065","name":"View Issue"}}

robhunt3r commented 9 years ago

@dbu I've created a PR for the readme as it hadn't any information about this. I think we can close this issue if all of members are ok with the solution.

TroodoNmike commented 9 years ago

Just a note from me, Im using sonata phpcr admin with CMF and I have just had exactly the same issue. Problem solved when adding:

{% block burgov_key_value_widget %}
    {{- block('sonata_type_native_collection_widget') -}}
{% endblock %}

into SonataAdminBundle:Form:form_admin_fields.html.twig

After testing that I have registered a new form resource in app.config file and then moved code from above into separate twig template

dbu commented 9 years ago

thanks, adding this to the cmf doc as well now: https://github.com/symfony-cmf/symfony-cmf-docs/pull/674