THELIA Forum

Welcome to the THELIA support and discusssion forum

Announcement

Rejoignez la communauté sur le Discord Thelia : https://discord.gg/YgwpYEE3y3

Offline


Bonjour,

Je crée un formulaire sur la page product-edit via le dossier AdminIncludes de mon module. J'utilise un form_collection dans cette vue. Je voudrais savoir comment récupérer les valeurs enregistrer depuis la base de donnée pour pré remplir mes champs.

Je pense que j'ai besoin d'overrider l'url de la modification d'un produit pour y injecter mon formulaire :

$this->createForm('mymodule.product.color.form', 'form', ['form_collection_name' => $dataFromDatabase]);

Est-ce qu'il y a un autre moyen de peupler un formulaire via des données de la base dans une vue AdminIncludes ? Pour les champs "normaux" (form_field) je fais crée un boucle pour y injecter les données dans le value de mon form mais je pense que ce n'est pas l'idéal. Pour les form_collection ça ne semble pas être la bonne solution car il faut peupler la collection dans le createForm.

Merci d'avance.

Last edited by Rtransat (27-10-2016 11:55:24)

Offline


Le plus simple est d'utiliser les hooks (l'utilisation de AdminIncludes est déprécié depuis la 2.3).

Tu peux regarder ici pour les détails : http://thelia.net/forum/viewtopic.php?pid=71239#p71239

Pour un exemple de module qui utilise les hooks pour ajouter des champs en back-office, voir ici : https://github.com/roadster31/Tags


OpenStudio Toulouse

Offline


Merci wink. Mais je ne peux pas utiliser dans mon hook $this->createForm hmm. J'hérite de BaseHook pas du controller.

J'ai beau essayé d'instancier mon formulaire via new ProductColorForm($this->getRequest()); mais il faut que je trouve comment passer des données dans mon formulaire et j'ai une erreur comme quoi mon type custom (Could not load type "mymodule_color_type") n'existe pas alors que lors de la soumission j'ai pas le problème.


Et l'erreur lorsqu'un formulaire échoue la validation : [Le paramètre "category" est absent dans la boucle type: category-path, nom: category_path ]
C'est vraiment chiant, je sais pas si ça vient de la validation ou si jamais il fait pas la validation et que c'est lors de l'event qu'il lance une exception car mon champ est vide et donc il peut pas recharger la page.

Last edited by Rtransat (27-10-2016 15:57:50)

Offline


Regarde comment marche le module Tags, ça devrait t'aider, en particulier le trio Hook / EventListener / Controller.


OpenStudio Toulouse

Offline


Dans le module Tag tu te hook sur l'onglet général. Je me hook sur product.tab-content je ne peux donc pas utiliser l'event ProductEvent, j'utilise un que j'ai crée et que j'instancie dans mon controller en lui passant les data souhaité.

Mais même pour l'initialisation du formulaire ça ne fonctionne pas car dans ton module (de ce que j'ai vu) tu te hook sur un formulaire existant, moi c'est un formulaire qui n'existe pas et je dois l'instancier dans mon hook.

public function onProductTabContent(HookRenderEvent $event)
{
    $productId = $this->getRequest()->getProductId();
    $product = \Thelia\Model\ProductQuery::create()->findPk($productId);

    if ($product->getTemplateId() === (int) MyModule::getConfigValue(MyModule::CONFIG_TEMPLATE_ID)) {
        $event->add($this->render('product-edit-svg.html'));
    }
    else {
        $colors = [
            'colors_collection' => [
                ['color' => '#FFFFFF'],
                ['color' => '#FFFFFF'],
                ['color' => '#FFFFFF'],
            ],
        ];
        $form = new ProductColorForm($this->getRequest(), 'form', $colors);

        $event->add($this->render('product-edit-colors.html', ['form' => $form]));
    }

}

Dans mon formulaire par contre je peux faire ceci et j'ai données par défaut, mais j'aimerais le faire dans le hook pour récupérer les valeurs depuis la base de donnée si il y en a, sinon j'afficherai des valeurs par défaut.

$this->formBuilder->setData([
            'colors_collection' => [
                ['color' => '#FFFFFF'],
                ['color' => '#FFFFFF'],
                ['color' => '#FFFFFF'],
            ],
        ]);

La vue

<div class="general-block-decorator">
    <div class="row">
        <div class="col-md-12">
            <p class="title title-without-tabs">{intl d="mymodule.bo.default" l="Associated product"}</p>

            {form name="mymodule.product.color.form"}

                <form action="{url path="/admin/product/$product_id"}/mymodulecolor" method="POST">

                    {include
                    file = "includes/inner-form-toolbar.html"
                    hide_submit_buttons = false
                    hide_flags = true

                    page_url  = "{url path='/admin/products/update' product_id=$ID}"
                    close_url = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}"
                    }

                    {if $form_error}<div class="alert alert-danger">{$form_error_message}</div>{/if}

                    {form_hidden_fields form=$form}

                    <input type="hidden" name="product_id" value="{$product_id}">

                    {form_field field='success_url'}
                        <input type="hidden" name="{$name}" value="{url path='/admin/categories' category_id=$DEFAULT_CATEGORY}">
                    {/form_field}

                    {form_field form=$form field="product_svg_id"}
                        <div class="form-group {if $error}has-error{/if}">
                            <label for="{$label_attr.for}" class="control-label">{$label}</label>
                            <select name="{$name}" id="{$label_attr.for}" class="form-control">
                                <option value="0">{intl l="Choose a custom product" d="mymodule.bo.default"}</option>
                                {loop type="product" name="mymodule-product"}
                                    <option value="{$ID}">{$TITLE}</option>
                                {/loop}
                            </select>
                        </div>
                    {/form_field}

                    {form_collection form=$form collection="colors_collection"}
                        <div class="form-group {if $error}has-error{/if}">
                            {form_collection_field form=$form row=$row field="color"}
                                <label class="control-label">{$label}</label>
                                <input type="text" name="{$name}" id="{$label_attr.for}" class="form-control" value="{$value}" />
                            {/form_collection_field}
                        </div>
                    {/form_collection}

                </form>
            {/form}
        </div>
    </div>
</div>

Dans mon controller je fais ceci :

public function addColorAction($product_id)
{
    $form = $this->createForm('mymodule.product.color.form');

    $error_message = null;

    try {
        $validateForm = $this->validateForm($form);

        $data = $validateForm->getData();
        // ProductColorEvent est un event que j'ai crée pour ce besoin
        $event = new ProductColorEvent(
            $this->getRequest()->getProductId(),
            $data['product_svg_id'],
            $data['colors_collection']
        );

        $this->dispatch('mymodule.product.color.create', $event); // Je sauvegarde dans mon Listener

        if ($this->getRequest()->get('save_mode') == 'stay') {
            return $this->generateRedirectFromRoute('admin.products.update', ['product_id' => $product_id]);
        } else {
            return $this->generateSuccessRedirect($form);
        }

    } catch (\Exception $e) {
        $error_message = $e->getMessage();

        Tlog::getInstance()->error("Failed to validate mymodule.product.color.form: $error_message");
    }


    $this->setupFormErrorContext(
        'Fail to process Product Color form data',
        $error_message,
        $form
    );

    return $this->render("product-edit");
}

Mais pour le coup ça ne fonctionne pas hmm

Offline


J'ai pensé à quelque chose (vu que je m'arrache les cheveux sur la création d'un formulaire dans l'onglet module d'une modification de produit hmm

Est-ce que l'on peut créer des champs de formulaire de type "tableau" sans passer par une forme collection ?
Par exemple j'aurais un champ avec comme name "colors[]" comme ça dans ma vue je pourrais gérer l'ajout et la suppression de champ supplémentaire en JS.

Si ce n'est pas possible je vais sans doute créer l'input quand même sans passer par le form builder sad et récupérer comme un crado $_POST

Un exemple sur les form_collection dans la doc serait vraiment le bienvenue, surtout avec la création d'un formulaire (createForm ou une nouvelle instance du formulaire) que l'on passe à la vue avec les données.

Ou un module qui fait ça je suis preneur pour décortiquer le code wink

Offline


Pourquoi une form collection et pas un choice ?


OpenStudio Toulouse

Offline


Un choice si je regarde la doc de symfony c'est pour un select, checkbox et radio ?
Dans mon cas les valeurs sont arbitraires, on peut y mettre la valeur souhaité et le nombre de champ est dynamique (ajout et suppression d'input via du JS)

Last edited by Rtransat (28-10-2016 08:31:49)

Offline

Offline


Je me suis passé du form collection encore une fois. J'ai un champ texte non requis et dans la vue je déclare le name comme ceci : name="{$name}[]"