Ajax: get partial blade template

sage9
blade

#1

Hello.

I’m trying to define various modal (popup) templates in my new WP Sage environment and then get them via Ajax call based on the provided “type” ID.

For example, modal with “type” 1 would have a centered title, image on the left and text on the right. The one with “type” 2 would have a title on a different place, then text on left, image on right, and another row the other way around. Modal type is selected when adding a modal in backend (custom post type) - based on this, proper content fields appear and must be filled in.

What I’m trying now is this:

  1. When you click a certain button with a given data attribute, Ajax call is made to WP Rest API, which gets all the content for the modal which will be opened. You also get modal type (1,2,3 …). This works as expected already. (data from ACF fyi).

  2. Based on the given modal type, I’d like to fill in the existing modal already loaded on page (just the wrapper) with the modal template in views/ajax/modal1.blade.php (or modal2.blade.php etc.). I want to keep the modal as blade template because i includes certain files / components already and also it’s probably better to keep it that way, no ?

  3. Now I insert the received HTML/strings to the template via Javascript to display it to the user, and I make the modal visible.

How do I go about compiling the ajax-received modal templates before getting it?
“I should probably make a controller” I though, but there’s no actual ‘view’ for which this controller would work; it’s just for the partial templates for this modals.

Any suggestions/help appreciated. Perhaps I’m even complicating things.
First time Sage user, hopefully, this is not a total misunderstanding of the concepts here :slight_smile:

Thanks!


#2

Hi @trainoasis,

Take a look at this thread and see if that gets you headed in the right direction:


#3

Hey @mmirus, thanks for your time.

I saw that and it actually seemed helpful indeed at first, but I’m a bit at a loss : what ajax url to call to get the appropriate data? How do I expose a certain URL (my controller that has a public static method inside which returns Template(…)). Certainly not just “…/views/ajax/modal1.blade.php” or something like that? This of course just gets the actual data within.

Still did not wrap my head around this 100% it seems!


#4

Hey @trainoasis,

I think your best bet is to do a wp_ajax call. https://codex.wordpress.org/AJAX_in_Plugins

The action you hook onto that call should prepare any data your partial needs and then call Template() passing in the partial path and the data. See the thread I linked to above and @MWDelaney’s post about passing data.

The action could be a static method on a controller (the app controller, for example).

Does that help get you any further in the process?


#5

That indeed helped a lot, thanks.

Got it working by using a separate controller for ajax stuff (to store ajax calls in the future also).

Just as a reference or help to someone else, what I did:

In setup.php:

/**
 * Ajax stuff
 */
add_action( 'wp_ajax_get_modal', 'Ajax::getModalTemplateHTML' ); 
add_action( 'wp_ajax_nopriv_get_modal', 'Ajax::getModalTemplateHTML' );

In a new file called ajax.php under app/controllers/:

namespace App;

use Sober\Controller\Controller;

class Ajax extends Controller
{
	public static function getModalTemplateHTML($popup_type = 1) {
		if(isset($_POST['popup_type'])) {
			$popup_type = (int)$_POST['popup_type'];
		}
		echo Template('ajax.modal'.$popup_type, ['data' => 'stuff']);
    	wp_die();
	}
}

And lastly in common.js (or any other) got the data via $.ajax:

$.ajax({
            url: GLOBAL_OBJECT.ajax_url,
            method: 'POST',
            data: { action: 'get_modal', popup_type: data.popup_type },
          }).done(function (data) {
            console.warn("FILL THE DATA IN THE MODAL WITH what you got from ajax");
        $('#modal-content').html(data); // this way I get a modal template; now I  can fill it with the data provided by a previous ajax to the REST API :) 
      });

If there’s a better/more correct approach to this, please do let me know :slight_smile:


#6

Glad you got it working, and thanks for sharing.

Speculatively, another way of accomplishing this would be to move your code out of controllers and setup.php and put it in app/ajax.php.

The reasons I explored this:

  1. Using a controller here that’s run via separate actions unrelated to how the controller normally functions feels a little strange / out of place to me. Moving it out of there makes it clear that the ajax controller isn’t run as part of the normal template loading process like the other controllers are.
  2. Currently if you want to add more AJAX hooks you would need to edit setup.php every time on top of your ajax.php file. Moving the add_action calls to it make it a little more self-contained.

But at the end of the day if your current setup is working and fits with how you want to organize your theme I don’t know if there’s any real advantage to doing it this way.

Here’s how you would set this up…

Create app/ajax.php and put your AJAX-related code in there:

<?php

namespace App;

class Ajax
{
    public function __construct()
    {
        add_action('wp_ajax_get_modal', [$this, 'myMethod']);
        add_action('wp_ajax_nopriv_get_modal', [$this, 'myMethod']);
    }

    public function myMethod()
    {
        echo 'AJAX response here';
        wp_die();
    }
}

new Ajax();

Add ‘ajax’ to the array of files loaded by Sage in functions.php:

/**
 * Sage required files
 *
 * The mapped array determines the code library included in your theme.
 * Add or remove files to the array as needed. Supports child theme overrides.
 */
array_map(function ($file) use ($sage_error) {
    $file = "../app/{$file}.php";
    if (!locate_template($file, true, true)) {
        $sage_error(sprintf(__('Error locating <code>%s</code> for inclusion.', 'sage'), $file), 'File not found');
    }
}, ['helpers', 'setup', 'filters', 'admin', 'ajax']);

Your JS shouldn’t need to change.


#7

Hello @mmirus.

That’s indeed a nicer approach there! Using it now and it feels much cleaner and better organised, which is the whole point of using Sage :smiley:.

Thanks for your help, very much appreciated, love Sage so far! Gotta move to Bedrock too!