Hinzufügen eines Bildformularelements zu einem Formular zum Hinzufügen / Bearbeiten

12

Ich erstelle ein CRUD-Modul für Magento 2 unter Verwendung von UI-Komponenten für die Administratorliste und das Formular, und eine meiner Entitäten verfügt über ein Bildfeld.
Aber ich kann es nicht so machen, wie es sollte.
So sollte es funktionieren.
Im Hinzufügungs- oder Bearbeitungsmodus ohne hochgeladenes Bild sollte es wie eine einfache Dateieingabe aussehen.

Wenn eine Datei hochgeladen wird, sollte die Bildvorschau und ein Löschfeld darunter angezeigt werden.

Ich suche nicht genau diesen Entwurf. Es könnte anders aussehen, aber die gleiche Funktionalität haben.

In Magento 1 konnte ich dies tun, indem ich meinen eigenen Block-Renderer erstellte

class {{Namespace}}_{{Module}}_Block_Adminhtml_{{Entity}}_Helper_Image extends Varien_Data_Form_Element_Image
{
    protected function _getUrl()
    {
        $url = false;
        if ($this->getValue()) {
            $url = Mage::helper('{{namespace}}_{{module}}/{{entity}}_image')->getImageBaseUrl().$this->getValue();
        }
        return $url;
    }
}

Und dies in meinem Formularblock hinzufügen

    $fieldset->addType(
        'image',
        Mage::getConfig()->getBlockClassName('{{namespace}}_{{module}}/adminhtml_{{entity}}_helper_image')
    );

Ich habe aber keinen Formularblock in Magento 2.
Ich weiß, dass ich einen Klassennamen für ein Formularfeld in der UI-Komponentendatei verwenden kann

    <field name="image" class="Class\Name\Here">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="dataType" xsi:type="string">text</item>
                <item name="label" xsi:type="string" translate="true">Resume</item>
                <item name="formElement" xsi:type="string">image</item>
                <item name="source" xsi:type="string">[entity]</item>
                <item name="dataScope" xsi:type="string">image</item>
            </item>
        </argument>
    </field>

Natürlich muss ich diese Klasse erstellen, aber was soll ich erweitern?
Ich weiß nur, dass ich das Interface implementieren muss, Magento\Framework\View\Element\UiComponentInterfaceaber ich habe nichts gefunden, was ich erweitern könnte.
Meine eigentliche Frage lautet also: Kann ich eine Klasse erweitern, um das gewünschte Verhalten zu erreichen? Wenn nicht, wie kann ich diesen Elementrenderer erstellen?

Marius
quelle
Hallo @Marius, ich habe versucht, anhand Ihres Beispiels Produktbilder zu meiner benutzerdefinierten Raster-Bearbeitungsseite hinzuzufügen, habe jedoch folgenden Fehler erhalten: Schwerwiegender Fehler: Die Klasse 'Varien_Data_Form_Element_' wurde in ... \ lib \ Varien \ Data \ Form nicht gefunden \ Abstract.php on line 146
bestwebdevs

Antworten:

21

Ich habe einen Weg gefunden, dies zu tun, ohne dass eine Klasse an das Feld angehängt werden muss. Ich meine, es gibt eine Klasse, die an das Formularelement angehängt ist, aber nicht als Renderer.
Die Spalte sollte folgendermaßen definiert sein:

<field name="image">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="dataType" xsi:type="string">string</item>
            <item name="source" xsi:type="string">[entity]</item>
            <item name="label" xsi:type="string" translate="true">Image</item>
            <item name="visible" xsi:type="boolean">true</item>
            <item name="formElement" xsi:type="string">fileUploader</item>
            <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
            <item name="previewTmpl" xsi:type="string">[Namespace]_[Module]/image-preview</item>
            <item name="required" xsi:type="boolean">false</item>
            <item name="uploaderConfig" xsi:type="array">
                <item name="url" xsi:type="url" path="[namespace_module]/[entity]_image/upload"/>
            </item>
        </item>
    </argument>
</field>

Ich musste auch die Vorschau-Vorlagendatei erstellen, auf die von verwiesen wird [Namespace]_[Module]/image-preview.
Das app/code/[Namespace]/[Module]/view/adminhtml/web/template/image-preview.htmlsieht so aus:

<div class="file-uploader-summary">
    <div class="file-uploader-preview">
        <a attr="href: $parent.getFilePreview($file)" target="_blank">
            <img
                class="preview-image"
                tabindex="0"
                event="load: $parent.onPreviewLoad.bind($parent)"
                attr="
                    src: $parent.getFilePreview($file),
                    alt: $file.name">
        </a>

        <div class="actions">
            <button
                type="button"
                class="action-remove"
                data-role="delete-button"
                attr="title: $t('Delete image')"
                click="$parent.removeFile.bind($parent, $file)">
                <span translate="'Delete image'"/>
            </button>
        </div>
    </div>

    <div class="file-uploader-filename" text="$file.name"/>
    <div class="file-uploader-meta">
        <text args="$file.previewWidth"/>x<text args="$file.previewHeight"/>
    </div>
</div>

Dieser Code generiert ein Feld wie das folgende:

Nach dem Hochladen eines Bildes (in Echtzeit) sieht es so aus:

Das url Element in der uploaderConfigist die URL, unter der das Bild beim Hochladen veröffentlicht wird. Also musste ich das auch schaffen:

namespace [Namespace]\[Module]\Controller\Adminhtml\[Entity]\Image;

use Magento\Framework\Controller\ResultFactory;

/**
 * Class Upload
 */
class Upload extends \Magento\Backend\App\Action
{
    /**
     * Image uploader
     *
     * @var \[Namespace]\[Module]\Model\ImageUploader
     */
    protected $imageUploader;

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \[Namespace]\[Module]\Model\ImageUploader $imageUploader
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \[Namespace]\[Module]\Model\ImageUploader $imageUploader
    ) {
        parent::__construct($context);
        $this->imageUploader = $imageUploader;
    }

    /**
     * Check admin permissions for this controller
     *
     * @return boolean
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('[Namespace]_[Module]::[entity]');
    }

    /**
     * Upload file controller action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        try {
            $result = $this->imageUploader->saveFileToTmpDir('image');

            $result['cookie'] = [
                'name' => $this->_getSession()->getName(),
                'value' => $this->_getSession()->getSessionId(),
                'lifetime' => $this->_getSession()->getCookieLifetime(),
                'path' => $this->_getSession()->getCookiePath(),
                'domain' => $this->_getSession()->getCookieDomain(),
            ];
        } catch (\Exception $e) {
            $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
        }
        return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
    }
}

Diese Klasse verwendet eine [Namespace]\[Module]\Model\ImageUploaderähnliche Instanz wie \Magento\Catalog\Model\ImageUploader.

Das scheint zu funktionieren. Ich habe immer noch Probleme, das Bild in der Datenbank zu speichern, aber das ist ein ganz anderes Problem.
Ich habe als Inspiration das imageFeld für die Kategorie Entität verwendet

Marius
quelle
Ich kann ein Bild erfolgreich hochladen und den Bildnamen in der Datenbank speichern. Wenn ich den soeben erstellten Datensatz öffne, werden alle Felder außer dem Bildfeld wie erwartet angezeigt. Wenn ich das Bildfeld in ein normales "Text" -Feld ändere, wird es angezeigt. Hast du eine Idee dazu?
Nero
1
@Nero. Sie benötigen den Bildwert in einem bestimmten json-Format. Hier ist ein Beispiel, wie Sie es in den richtigen
Marius
Ich möchte kein Bild hochladen, aber ich möchte das Bild in Admin-UI-Form anzeigen. Eigentlich lade ich das Bild vom Frontend-Formular hoch und möchte es in Admin-UI-Form anzeigen. Bitte helfen Sie mir dabei
Sneha Panchal
Es ist ein Fehler in [Namespace] [Modul] \ Controller \ Adminhtml [Entität] \ Image \ upload.php in Zeile 61 aufgetreten. Bitte überprüfen und aktualisieren Sie die Antwort.
Prinz Patel
@ PrincePatel Was ist die Fehlermeldung?
Marius
2

Ja, die Klasse, die Sie erweitern sollten, ist \Magento\Ui\Component\Form\Element\AbstractElement.

Diese Klasse implementiert die ElementInterfaceErweiterung, auf die UiComponentInterfaceSie sich beziehen.

Wenn Sie außerdem die unter deklarierten Komponenten überprüfen Magento\Ui\Component\Form\Element, können Sie feststellen, dass sie alle diese Klasse erweitern.

Der Grund, warum ich diese Klasse wählen würde, ist, dass die renderMethode \Magento\Backend\Block\Widget\Form\Renderer\Elementnur einen solchen Klassentyp akzeptiert:(Dies ist eigentlich eine Instanz Magento\Framework\Data\Form\Element\AbstractElement, die akzeptiert wird, nicht \Magento\Ui\Component\Form\Element\AbstractElement)

Raphael bei Digital Pianism
quelle
Gibt es Hinweise, wie meine Klasse aussehen sollte?
Marius
@Marius hmmm Ich bin mir nicht sicher, ich werde versuchen es herauszufinden
Raphael bei Digital Pianism
1
Ich glaube nicht, dass Sie das noch tun müssen. Ich glaube, ich habe eine Lösung gefunden, ohne eine Klasse in der UI-Komponente zu verwenden, aber ich muss sie zuerst testen.
Marius
@Marius hmmmm Ich glaube, ich habe mich geirrt. Ich denke, Sie sollten das überprüfen: github.com/magento/magento2-samples/tree/master/…
Raphael bei Digital Pianism