Select Image from Site and Page

I have a set of images that get used a lot on my site. So instead of saving them in every folder again I would love an image select field that combine images from the current page and the site folder.

I looked at the image field and did not see an option for that and in docs for select I don’t see how to build the query

If there is a fieldtype already I did not find it (yet)

Thanks in advance :slight_smile:

That’s not possible out of the box, but you can create your own custom select field.

I was kind of hoping someone already did that :innocent:

If you don’t want to create a field, maybe the field-toggle field can be an alternative:

Choose whether you want to select a page or site image, and then show the corresponding select field.

so a new field plugin would be very simple. I only need to access the Site images. The Docs only tell how to access the current page tho …

You only want to list the images of the site? Simply use the select field like this:

image:
  type:  select
  options: query
  query:
    page: /
    fetch: images

If you want the option to list either the site or the page images you can use the fieldtoggle field like texnixe suggested:

This looks like that in the backend:

imagetoggle:
  label:          Image location
  type:           fieldtoggle
  options:
    site:         "Site"
    page:         "Page"
  show:
    site:         siteimage
    page:         pageimage
  hide:
    site:         pageimage
    page:         siteimage
siteimage:
  label:          Image
  type:           select
  options:        query
  query:
    page:         /
    fetch:        images
pageimage:
  label:          Image
  type:           select
  options:        images
1 Like

somehow does not fetch site images :frowning:

I have a .png and two .jpg and the selector gives me two empty entries …

Please add the value and text options to make the files “visible”:

  siteimage:
    label: Image
    type: select
    options: query
    query:
      page: /
      fetch: images
      text: '{{filename}}'
      value: '{{filename}}'
1 Like

that did the trick :slight_smile:

maybe you could add that snippet to the docs ?

Sorry to drudge up an old topic, but seeing as this was a relevant search result in my own googling, I thought this may be of value to someone.

On every image select, I wanted to see all images in the site, and all images in the page (and I didn’t want to lose the image preview of selected image in panel). So I…

  1. copied the original field at panel/app/fields/image to site/fields/images
  2. renamed all the files from image.* to images.*
  3. change the class name in site/fields/images/images.php from ImageField to ImagesField.
  4. change the options function in site/fields/images/images.php to…
  public function options() {
    $options = [];
    $site = panel()->site();
    foreach($site->images() as $image) {
      $options[$image->filename()] = $image;
    }
    foreach($this->images() as $image) {
      $options[$image->filename()] = $image;
    }
    return $options;
  }
  1. Then in the blueprint, I changed “type: image” to “type: images”.

If a file exists in both, it should be overwritten by the page version in the list.

How do you fetch your images in your template if you only store the filename?

1 Like

I ended up using this. Perhaps it’s not ideal. Would be better to work the check into the function itself or store the url itself as the value perhaps.

if($image = $page->background()->toFile() ? $page->background()->toFile() : $site->image($page->background()->toString())){
	$background_style = 'style="background-image: url(\'' . $image->url() . '\')"';
}

I think you are probably better off with storing the URI.

$image->uri was returning the url without “content/” in it. I suppose that’s fine if you want to append content to it manually, but I preferred to use URL so I don’t have to tamper with the resulting value. Perhaps I was doing something incorrectly?

	public function options() {
	  $options = [];
	  $site = panel()->site();
	  foreach($site->images() as $image) {
	    $options[$image->url()] = $image;
	  }
	  foreach($this->images() as $image) {
	    $options[$image->url()] = $image;
	  }
	  return $options;
	}

To use in template:

$background_style = ($image_url = $page->background()->toString() !== '' ? $page->background()->toString() : NULL) ? 'style="background-image: url(\'' . $image_url . '\')"' : '';

The only thing I don’t like it about this, is that now the options on the $page level don’t overwrite the options on the $site level. That seemed like a nice graceful override that I could appreciate. If one were to use generic names like “hero.jpg” then it would always show a “hero.jpg” in the list, but if a page doesn’t have one, it will inherit it from $site default “hero.jpg”. But the list doesn’t become cluttered with duplicate file names.