Flex-objects directory with each entry as a mini form? for a classified ads page?

Hey everybody,

I want to do a fairly simple classified ads page. I thought this should be easy with a designated flex-objects directory, and I’ve got that done (a page that lists directory entries).

But I would like a button next to each ad/entry that says “I’m interested”, and upon clicking it an email gets sent to the advertiser. The problem here is, how do I do this in Grav, either with or without using the forms plugin? I’d need a form for each flex entry…

I could put in HTML forms manually, but where would I put the PHP code to do all the processing, and how would I present the resulting feedback to the user who clicked the button?

Thank you for your ideas!

@Netzhexe, Why not use Typescript/Js and call an async fetch submitting the name/id of the ad to the server?

A simple unpolished example:

Inject the following inline script using Asset Manager

<script>
  async function sentEmail(topic) {
    try {
      const response = await fetch(
        window.location.pathname + 'subscribeToAd:' + topic,
        {
          method: 'POST',
          body: JSON.stringify(topic),
        }
      );
      
      if (response.ok) {
        // handle success
        const returnValue = await response.json();
        alert(returnValue);
      } else {
        // handle issue
        alert('Houston, we have a problem');
      }
    } catch (error) {
      // handle Error
      alert('Houston, we crashed...');
    }
  }
</script>

For each add, you could add a anchor which calls the sendEmail() function with a topic as parameter.

<a href="#" onclick="sentEmail('topic1')">Subscribe</a>

Of course you could use a button and add an event listener to it which calls the sendEmail() function.

In a plugin, at event onPluginInitialized check for param used by fetch and handle submitted data:

if ($this->grav['uri']->param('subscribeToAd') !== false) {
  $topic = json_decode(file_get_contents('php://input'), true);
  $user = $this->grav['user'];

  $response = $this->sendEmail($topic, $user);

  echo json_encode($response);
  die();
}

Using a form as an alternative:

  • create a single form containing a list/grid of checkboxes with the ad as title
  • when user clicks submit button, process submitted checkboxes on server in event onFormProcessed

Hey, thank you. I’m a little wary of relying on Javascript for essential functions… I just like to have fallbacks. Maybe I’m overthinking this though.

The solution using a form brings up another question: does onFormProcessed also work for forms that I create myself in a twig template, and not with the Forms plugin? Because the checkbox solution was exactly what I had in mind :upside_down_face:

@Netzhexe,

I’m a little wary of relying on Javascript for essential functions… I just like to have fallbacks.

What issues do you foresee…? Almost the entire web depends on JavaScript, doesn’t it?

question: does onFormProcessed also work for forms that I create myself in a twig template, and not with the Forms plugin?

I would be surprised if the Forms plugin would handle custom forms…

I guess you will have to handle the form in PHP yourself using $_POST.

In case anyone’s thinking about doing something similar, I ended up using a flex directory for the entries and a bunch of custom php for the page handling and to send emails. Works alright so far, like I said it’s not a big thing. I added some custom fields to member registration as well, that was interesting.