WordPress Data Attribute Pattern

Recently, I’ve had to push things back and forth between PHP and javascript but it seemed simpler at the time to use data attributes rather than doing it purely in javascript. It’s likely that I am wrong and stupid and I should have done it all in javascript but I’ll document it anyway. I never know when I’ll want to repeat things that are bad ideas.

For this example, we’ll populate a Bootstrap Modal via javascript with the content of a particular post.

PHP Portion

The following code gets a custom post type and loops through the results, building a carousel of options.

The portion that we’ll pay extra attention to is htmlspecialchars(wpautop(get_the_content()),ENT_QUOTES);.

I crammed it all together which is a crummy way to do things but I’m tired and it’s early Saturday morning and I’m writing a blog post.

Let’s back out the pieces, starting on the inside.

get_the_content is just how we get WP’s post content.

wpautop makes sure we get the line breaks as paragraph tags.

htmlspecialchars makes sure that any special characters as returned as HTML so it won’t break our HTML when we echo it out in the data attribute data-bs-content='{$content}’.

function bad_idea_methods_carousel(){
	$html = '';
	$args = array(
		'post_type' => array('methods'),
		'posts_per_page' => 20,
    	'nopaging' => true, 
	);
	$active = 'active';
	$method_query = new WP_Query( $args );
	// The Loop
	if ( $method_query->have_posts() ) :
		while ( $method_query->have_posts() ) : $method_query->the_post();
			$title = get_the_title();
			$content =  htmlspecialchars(wpautop(get_the_content()),ENT_QUOTES);
			$excerpt = get_the_excerpt();
			$clean_excerpt = substr($excerpt, 0, 320);
			$post_id = get_the_ID();
			$item = "
				<div class='carousel-item {$active}'>
					<div class='col-md-4'>
						<div class='card method'>
							<h2>{$title}</h2>
							<div class='method-content'>
								{$clean_excerpt} . . .								
							</div>
							<button type='button' class='btn btn-primary method-button' data-bs-toggle='modal' data-bs-target='#methodModal' aria-label='Method details for {$title}.' data-bs-method='{$title}' data-bs-content='{$content}'>Method Details</button>
						</div>
					</div>
				</div>";
		$html .= $item;
		$active = '';
		endwhile;
		return $html;
		// No value.
	else :
		// Do something...
	endif;

}

Javascript Portion

Now we’ve got an HTML button that looks something like this.

<button type="button" class="btn btn-primary method-button" data-bs-toggle="modal" data-bs-target="#methodModal" aria-label="Method details for Design Thinking." data-bs-method="Design Thinking" data-bs-content="<p>The use of blah blah blah.</p>
<p>In applying this foo bar buzz bang etc.</p>
">Method Details</button>

We can modify the standard Bootstrap varying modal content a bit to get this. Using innerHTML (rather than textContent) takes our various HTML attributes and makes them behave like you’d expect.

if(document.getElementById('methodModal')){
	let exampleModal = document.getElementById('methodModal');
	exampleModal.addEventListener('show.bs.modal', function (event) {
	  // Button that triggered the modal
	  let button = event.relatedTarget
	  //get title from data attribute
	  let methodTitle = button.getAttribute('data-bs-method')
	  //get content from data attribute
	  let methodContent= button.getAttribute('data-bs-content')
	  
	  //get destinations
	  let modalTitle = exampleModal.querySelector('.modal-title')
	  let modalBodyInput = exampleModal.querySelector('.modal-body')

	  //set destinations with variable content
	  modalTitle.textContent = methodTitle
	  modalBodyInput.innerHTML = methodContent
	})

}