Comment envoyer des données supplémentaires lors de la sauvegarde pour réaliser un traitement spécifique ?

Prérequis

Afin de pouvoir suivre ce guide, il faut préalablement savoir Comment déclencher un code javascript lors de la sélection d’un menu spécifique ?.

Comment procéder ?

Dans notre exemple, on souhaite afficher un message provenant du serveur lorsque le prix d’un PLAT a été changé. La méthode addCustomClientData permet d’ajouter des données supplémentaires depuis le client.

Recommandations

Si vous n’êtes pas familier avec la méthode addCustomClientData, il est recommandé de lire la documentation associée disponible ici

Commençons par rajouter le Smart Field plat_price_difference qui contiendra la différence de prix. Cette différence sera calculée côté client.

Modifier le fichier src/vendor/Cogip/Restauratec/SmartStructures/Plat/100-PlatStructure.xml :













 














<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<smart:config xmlns:smart="https://platform.anakeen.com/4/schemas/smart/1.0">
    <smart:structure-configuration name="PLAT" label="Plat">
        <smart:extends ref="CONSOMMABLE"/> <!-- La smart structure PLAT hérite de la smart structure CONSOMMABLE -->
        <smart:icon file="plat.png"/>
        <smart:class>Cogip\Restauratec\SmartStructures\Plat\PlatBehavior</smart:class>
        <smart:fields reset="true">
            <!-- extended="true" indique que l’on récupère ici la frame du parent (Consommable) à laquelle on ajoute d’autres Smart Fields -->
            <smart:field-set name="consommable_frame" extended="true">
                <smart:field-enum name="plat_type" label="Type de plat" relation="Plat_Type" access="Read" />
                <smart:field-date name="plat_validity_date" label="Disponible jusqu’au" access="Read" />
                <smart:field-text name="plat_abstract" label="Résumé" access="ReadWrite" />
                <smart:field-double name="plat_price_difference" label="Différence de prix" access="ReadWrite"/>
                <smart:field-date name="plat_creation_date" label="Date de création du plat" access="ReadWrite" />
                <smart:field-image name="plat_image" label="Image du plat" access="ReadWrite"/>
            </smart:field-set>
        </smart:fields>
        <smart:hooks />
        <smart:defaults>
            <smart:default field="plat_abstract">Entrez un résumé...</smart:default>
            <smart:default field="plat_creation_date">
                <smart:field-callable function="::getCreationDate"/>
            </smart:default>
        </smart:defaults>
    </smart:structure-configuration>
</smart:config>

Modifions le fichier src/public/platEdit.js pour ajouter nos données supplémentaires :















 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

window.ank.smartElement.globalController.registerFunction("platEdit", (controller) => {
  controller.addEventListener("ready", function addListeners(event, documentObject, data) {
    controller.addEventListener("afterSave", function fetchConsultationView(
      event,
      currentSmartElement,
      previousSmartElement
    ) {
      controller.fetchSmartElement({
        initid: currentSmartElement.initid,
        viewId: "!defaultConsultation",
      });
    });
  });

  const oldPrice = controller.getValue("consommable_price_incl_vat");

  controller.addEventListener("smartFieldChange", function addCustomClientData(
    event,
    smartElement,
    smartField,
    values
  ) {
    if (smartField.id === "consommable_price_incl_vat") {
      const newPrice = values.current;
      const priceDifference = newPrice.value - oldPrice.value;
      controller.addCustomClientData({ priceDifference });
    }
  });
});

On peut alors récupérer les données client supplémentaires du côté du serveur en utilisant la méthode setCustomClientData.

Recommandations

Si vous n’êtes pas familier avec la méthode setCustomClientData, il est recommandé de lire la documentation associée disponible ici

Modifier le fichier src/vendor/Cogip/Restauratec/SmartStructures/Plat/Render/PlatEditRender.php :





















































 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


<?php
namespace Cogip\Restauratec\SmartStructures\Plat\Render;

use Anakeen\Ui\CommonRenderOptions;
use Anakeen\Ui\EnumRenderOptions;
use Anakeen\Ui\FrameRenderOptions;
use Anakeen\Ui\RenderAttributeVisibilities;
use Anakeen\Ui\RenderOptions;
use Cogip\Restauratec\SmartStructures\Consommable\Render\ConsommableEditRender;
use SmartStructure\Fields\Plat as PlatFields;

class PlatEditRender extends ConsommableEditRender
{
    public function getOptions(\Anakeen\Core\Internal\SmartElement $document): RenderOptions
    {
        $options = parent::getOptions($document);
        $options->enum(PlatFields::plat_type)->setDisplay(EnumRenderOptions::verticalDisplay);
        $options->commonOption()->setLabelPosition(CommonRenderOptions::upPosition);
        $options->frame(PlatFields::consommable_frame) ->setResponsiveColumns(
            array(
                [
                    "number" => 2,
                    "minWidth" => "60rem",
                    "maxWidth" => "100rem",
                    "direction" => FrameRenderOptions::topBottomDirection
                ],
                [
                    "number" => 3,
                    "minWidth" => "100rem",
                    "maxWidth" => "140rem",
                    "direction" => FrameRenderOptions::topBottomDirection],
                [
                    "number" => 4,
                    "minWidth" => "140rem",
                    "maxWidth" => "160rem",
                    "direction" => FrameRenderOptions::topBottomDirection],
                [
                    "number" => 5,
                    "minWidth" => "160rem",
                    "direction" => FrameRenderOptions::topBottomDirection],
            )
        );
        return $options;
    }

    public function getJsReferences(\Anakeen\Core\Internal\SmartElement $document = null)
    {
        $jsRefs = parent::getJsReferences($document);
        $jsRefs['platEdit'] = new \Anakeen\Ui\JsAssetReference("/platEdit.js");
        return $jsRefs;
    }

    public function setCustomClientData(\Anakeen\Core\Internal\SmartElement $document, $data)
    {
        parent::setCustomClientData($document, $data);
        if (!empty($data) && array_key_exists("priceDifference", $data)) {
            $priceDiff = $data["priceDifference"];
            if (!empty($priceDiff)) {
                $document->setAttributeValue(PlatFields::plat_price_difference, $priceDiff);
                $document->store();
            }
        }
    }

    public function getVisibilities(\Anakeen\Core\Internal\SmartElement $document, \SmartStructure\Mask $mask = null): RenderAttributeVisibilities
    {
        $vis = parent::getVisibilities($document, $mask);
        $vis->setVisibility(PlatFields::plat_price_difference, RenderAttributeVisibilities::HiddenVisibility);
        return $vis;
    }
}

Astuce

Pensez à générer les stubs. Cela a pour but d’extraire les constantes des différents fichiers de configuration .xml des SmartStructures que vous possédez. Cela apportera ici une complétion sur les Smart Fields, paramètres de Smart Structure, étapes et transitions des cycles de vie, aussi bien dans le PHP que dans le JavaScript. Pour cela :

npx @anakeen/anakeen-cli generateStubs

Affichons un message sur la vue de consultation en modifiant src/vendor/Cogip/Restauratec/SmartStructures/Plat/Render/PlatViewRender.php :













































 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


<?php

namespace Cogip\Restauratec\SmartStructures\Plat\Render;

use Anakeen\Core\Internal\SmartElement;
use Anakeen\Routes\Core\Lib\ApiMessage;
use Anakeen\Ui\BarMenu;
use Anakeen\Ui\ItemMenu;
use Anakeen\Ui\MenuTargetOptions;
use Anakeen\Ui\RenderAttributeVisibilities;
use Cogip\Restauratec\SmartStructures\Consommable\Render\ConsommableViewRender;
use SmartStructure\Fields\Plat as PlatFields;

class PlatViewRender extends ConsommableViewRender
{

    /**
     * @param SmartElement $document
     * @return BarMenu
     * @throws \Anakeen\Core\DocManager\Exception
     * @throws \Anakeen\Exception
     * @throws \Anakeen\Database\Exception
     * @throws \Anakeen\Search\Exception
     */
    public function getMenu(SmartElement $document): BarMenu
    {
        $menu = parent::getMenu($document);
        $imagePlat= $document ->getFileLink(PlatFields::plat_image);
        if(!empty($imagePlat)){
            $itemImage = new ItemMenu("platImage");
            $url = sprintf("%s?inline=true&inline=yes",
                $imagePlat
            );
            $itemImage->setUrl($url);

            $option = new MenuTargetOptions();
            $option->windowHeight = 400;
            $option->windowWidth = 700;
            $itemImage->setTarget("_dialog", $option);
            $itemImage->setTextLabel("Afficher l’image");
            $menu->appendElement($itemImage);
        }
        return $menu;
    }

    public function getMessages(\Anakeen\Core\Internal\SmartElement $document)
    {
        $messages = parent::getMessages($document);
        $priceDiff = $document->getAttributeValue(PlatFields::plat_price_difference);
        if ($priceDiff !== 0) {
            $messages[] = new ApiMessage(sprintf("Le plat a changé de prix de %s euros", $priceDiff), ApiMessage::WARNING);
        }
        return $messages;
    }

    public function getVisibilities(\Anakeen\Core\Internal\SmartElement $document, \SmartStructure\Mask $mask = null): RenderAttributeVisibilities
    {
        $vis = parent::getVisibilities($document, $mask);
        $vis->setVisibility(PlatFields::plat_price_difference, RenderAttributeVisibilities::HiddenVisibility);
        return $vis;
    }
}

Recommandations

Si vous n’êtes pas familier avec les méthodes getMessages ou getVisibilities, vous pouvez suivre les How To correspondants disponibles ici ou ici.

Vous pouvez maintenant déployer vos modifications :

npx @anakeen/anakeen-cli deploy -c http://localhost:8080/control -s . -u admin -p anakeen --reinstall

Et voir le résultat sur un PLAT en création ou édition :

http://localhost:8080/api/v2/smart-elements/PLAT/views/!defaultCreation.html

customClientData

Et ensuite ?

Comment afficher des données serveur spécifiques sur une représentation ?