Explorar o código

Create recipe_image_previews.rst

Created cookbook entry about how to add image previews to edit forms
Christian Morgan %!s(int64=11) %!d(string=hai) anos
pai
achega
1afecc6a88
Modificáronse 1 ficheiros con 140 adicións e 0 borrados
  1. 140 0
      Resources/doc/reference/recipe_image_previews.rst

+ 140 - 0
Resources/doc/reference/recipe_image_previews.rst

@@ -0,0 +1,140 @@
+Showing image previews 
+======================
+
+This is a full working example of one way to add image previews to your create and 
+edit views in SonataAdmin.
+
+
+Pre-requisites
+--------------
+
+- you have already got the image files on a server somewhere and have a helper 
+  method to retrieve a publicly visible URL for that image, in this example that 
+  method is called ``Image::getWebPath()``
+- you have already set up an Admin to edit the object that contains the images,
+  now you just want to add the previews. In this example that class is called
+  ``ImageAdmin``
+
+.. note::
+
+    There is a separate cookbook recipe to demonstrate how to upload images
+    (and other files) using SonataAdmin.
+
+
+The recipe
+----------
+
+SonataAdmin lets us put raw HTML into the 'help' option for any given form field.
+We are going to use this functionality to embed an image tag when an image exists.
+
+To do this we need to:
+
+- get access to the ``Image`` instance from within ``ImageAdmin``
+- create an image tag based on the Image's URL
+- add a 'help' option to a field on the Image form to display the image tag
+
+For the sake of this example we will use some basic CSS to restrict the size of 
+the preview image (we are not going to generate and save special thumbnails).
+
+
+Basic example - for single layer Admins
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If we are working directly with our ``ImageAdmin`` class then getting hold of 
+the ``Image`` instance is simply a case of calling ``$this->getSubject()``. Since
+we are manipulating form fields we do this from within ``ImageAdmin::configureFormFields()``:
+
+.. code-block:: php
+
+    class ImageAdmin extends Admin
+    {
+        protected function configureFormFields(FormMapper $formMapper)
+        {
+            // get the current Image instance
+            $image = $this->getSubject();
+            
+            // use $fileFieldOptions so we can add other options to the field
+            $fileFieldOptions = array('required' => false);
+            if ($image && ($webPath = $image->getWebPath())) {
+                // add a 'help' option containing the preview's img tag
+                $fileFieldOptions['help'] = '<img src="'.$webPath.'" class="admin-preview" />';
+            }
+            
+            $formMapper
+                // ... other fields ...
+                ->add('file', 'file', $fileFieldOptions)
+            ;
+        }
+        // ...
+    }
+
+We then use CSS to restrict the max size of the image:
+
+.. code-block:: css
+
+    img.admin-preview {
+        max-height: 200px;
+        max-width: 200px;
+    }
+
+And that's all there is to it!
+
+However, this method does not work when the ``ImageAdmin`` can be embedded in other 
+Admins using the ``sonata_type_admin`` field type. For that we need...
+
+Advanced example - works with embedded Admins
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When one Admin is embedded in another Admin, $this->getSubject() does not return the
+instance under management by the embedded Admin. Instead we need to detect that our
+Admin class is embedded and use a different method:
+
+.. code-block:: php
+
+    class ImageAdmin extends Admin
+    {
+        protected function configureFormFields(FormMapper $formMapper)
+        {
+            if($this->hasParentFieldDescription()) { // this Admin is embedded
+                // $getter will be something like 'getlogoImage'
+                $getter = 'get' . $this->getParentFieldDescription()->getFieldName();
+
+                // get hold of the parent object
+                $parent = $this->getParentFieldDescription()->getAdmin()->getSubject();
+                if ($parent) {
+                    $image = $parent->$getter();
+                } else {
+                    $image = null;
+                }
+            } else {
+                $image = $this->getSubject();
+            }
+            
+            // use $fileFieldOptions so we can add other options to the field
+            $fileFieldOptions = array('required' => false);
+            if ($image && ($webPath = $image->getWebPath())) {
+                // add a 'help' option containing the preview's img tag
+                $fileFieldOptions['help'] = '<img src="'.$webPath.'" class="admin-preview" />';
+            }
+            
+            $formMapper
+                // ... other fields ...
+                ->add('file', 'file', $fileFieldOptions)
+            ;
+        }
+        // ...
+    }
+
+As you can see, the only change is how we retrieve set ``$image`` to the relevant Image instance.
+When our ImageAdmin is embedded we need to get the parent object first then use a getter to 
+retrieve the Image. From there on, everything else is the same.
+
+
+Notes
+-----
+
+If you have more than one level of embedding Admins this will (probably) not work. If you know of
+a more generic solution, please fork and update this recipe on GitHub. Similarly, if there are any
+errors or typos (or a much better way to do this) get involved and share your insights for the
+benefit of everyone.
+