select blog post module

SOLVE
Top Contributor

Hi,

 

Is it possible to generate a custom module that will allow a content author to choose related blog posts, perhaps a drop down select module that lists any blog post that contains a featured image?

 

I'm looking to generate a section/row at the bottom of a blog post that has an area displaying any further reading or related content. This is part of a projet looking at topic clusters.

 

Thanks

Reply
0 Upvotes
1 Accepted solution

Accepted Solutions
Regular Contributor

Well,

 

This sort of hacking isn't technically supported (there once was a tutorial showing this type of module hacking but it's gone now). BUT... it works none-the-less.

 

Try something like this in your Blog Post template:

{# Get 100 most recent posts... replace commas because it will break the comma-separated choice list #}

{% macro getBlogs() %}
{% set blog_list = blog_recent_posts('default', 100) %}
    Most Recent,
    {% for blog_post in blog_list %}
        {% if loop.last %}
            {{blog_post.name|replace(","," ")}}
        {% else %}
            {{blog_post.name|replace(","," ")}},
        {%endif%}
{% endfor %}
{% endmacro %}

  {# Get the blog post ID  #}
    
{%- macro getBlogId(search) -%}
    
    {% set blog_list = blog_recent_posts('default', 100) %}
        {% set found = 0 %}
        {% for blog_post in blog_list %}
            {% if search|lower|urlencode == blog_post.name|replace(","," ")|lower|urlencode && found == 0 %}
                {{blog_post.id}}
                {% set found = 1 %}
            {% else %}
            {% endif %}
            
            {% if (loop.last && found == 0)  %}
                {{blog_list[0].id }}
            {% endif %} 
   
        {% endfor %}
    {%- endmacro -%}

    {% set postOptions = getBlogs() %}

    {% choice "post_choice1" label='Choice 1', value='Most Recent', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice2" label='Choice 2', value='Most Recent', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice3" label='Choice 3', value='Most Recent', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice4" label='Choice 4', value='Most Recent', choices='{{postOptions}}' export_to_template_context=True %}

 {% set post1 = getBlogId(widget_data.post_choice1.value) %}
 {% set post2 = getBlogId(widget_data.post_choice2.value) %}
 {% set post3 = getBlogId(widget_data.post_choice3.value) %}
 {% set post4 = getBlogId(widget_data.post_choice4.value) %}
{% set choices = [post1,post2,post3,post4] %}

Basically what you get here is 4 drop-downs - each populated by a comma-separated list of recent post names.

 

You can then select one from the drop-down, and a separate function will populate variables with the blog post ID of those selections and put them in an array of IDs.

 

In an ideal world, just as @stefen mentioned, there's a blog_post_by_id() function that takes the ID as a parameter (if only we could just plug these IDs in there!) and you can pump out posts from the ID.

 

Alas you cannot... believe me I've tried every manner of fiddling with that variable to get it to work in the function but it WON'T work. I've got other situations where variables work VERY well in this type of blog_post_by_id() context, but this is not one of them. If you were to add an ID directly (again as @stefen mentioned) this would work fine.

 

But to do it dynamically we need something else.

 

What you'll have to do instead is wherever you want to put your related posts section / HubL For Loop, add something like this:

{% set recent_posts = blog_recent_posts('default', 100) %}
{% set found = 0 %}
{% for post in recent_posts %}
	{% for choice in choices %}
		{% if choice is string_containing post.id %}
			{# INSERT YOUR HTML TO RENDER THE BLOG POST %}
		{% endif %}
	{% endfor %}
{% endfor %}

Give it a try and see if it works, I didn't test the last bit (as my case only needed a single "featured post" so I just had 1 ID to look for (no second loop, just a simple {% if %} match case).

 

Good luck!

Reply
0 Upvotes
6 Replies 6
Advisor

@matttunney definitely possible! I don't know if you've seen this, but HubSpot has a nice little tutorial that automatically generates the related posts with the same topics: http://designers.hubspot.com/tutorials/creating-a-related-post-section-with-hubl

 

If you want something more curated, you'll probably have to make it a little more of a manual process e.g. choose a title, URL, image for each related post. EDIT: there is a function built-in to HubL that lets you output a blog post by ID: http://designers.hubspot.com/en/docs/hubl/hubl-supported-functions#blog-post-by-id Then all the editor would have to do is copy and paste the blog post IDs that they want.

--
Stefen Phelps
Web Developer / Co-founder
Kelp Creative Agency
Twitter — @stefen
Reply
0 Upvotes
Regular Contributor

Well,

 

This sort of hacking isn't technically supported (there once was a tutorial showing this type of module hacking but it's gone now). BUT... it works none-the-less.

 

Try something like this in your Blog Post template:

{# Get 100 most recent posts... replace commas because it will break the comma-separated choice list #}

{% macro getBlogs() %}
{% set blog_list = blog_recent_posts('default', 100) %}
    Most Recent,
    {% for blog_post in blog_list %}
        {% if loop.last %}
            {{blog_post.name|replace(","," ")}}
        {% else %}
            {{blog_post.name|replace(","," ")}},
        {%endif%}
{% endfor %}
{% endmacro %}

  {# Get the blog post ID  #}
    
{%- macro getBlogId(search) -%}
    
    {% set blog_list = blog_recent_posts('default', 100) %}
        {% set found = 0 %}
        {% for blog_post in blog_list %}
            {% if search|lower|urlencode == blog_post.name|replace(","," ")|lower|urlencode && found == 0 %}
                {{blog_post.id}}
                {% set found = 1 %}
            {% else %}
            {% endif %}
            
            {% if (loop.last && found == 0)  %}
                {{blog_list[0].id }}
            {% endif %} 
   
        {% endfor %}
    {%- endmacro -%}

    {% set postOptions = getBlogs() %}

    {% choice "post_choice1" label='Choice 1', value='Most Recent', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice2" label='Choice 2', value='Most Recent', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice3" label='Choice 3', value='Most Recent', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice4" label='Choice 4', value='Most Recent', choices='{{postOptions}}' export_to_template_context=True %}

 {% set post1 = getBlogId(widget_data.post_choice1.value) %}
 {% set post2 = getBlogId(widget_data.post_choice2.value) %}
 {% set post3 = getBlogId(widget_data.post_choice3.value) %}
 {% set post4 = getBlogId(widget_data.post_choice4.value) %}
{% set choices = [post1,post2,post3,post4] %}

Basically what you get here is 4 drop-downs - each populated by a comma-separated list of recent post names.

 

You can then select one from the drop-down, and a separate function will populate variables with the blog post ID of those selections and put them in an array of IDs.

 

In an ideal world, just as @stefen mentioned, there's a blog_post_by_id() function that takes the ID as a parameter (if only we could just plug these IDs in there!) and you can pump out posts from the ID.

 

Alas you cannot... believe me I've tried every manner of fiddling with that variable to get it to work in the function but it WON'T work. I've got other situations where variables work VERY well in this type of blog_post_by_id() context, but this is not one of them. If you were to add an ID directly (again as @stefen mentioned) this would work fine.

 

But to do it dynamically we need something else.

 

What you'll have to do instead is wherever you want to put your related posts section / HubL For Loop, add something like this:

{% set recent_posts = blog_recent_posts('default', 100) %}
{% set found = 0 %}
{% for post in recent_posts %}
	{% for choice in choices %}
		{% if choice is string_containing post.id %}
			{# INSERT YOUR HTML TO RENDER THE BLOG POST %}
		{% endif %}
	{% endfor %}
{% endfor %}

Give it a try and see if it works, I didn't test the last bit (as my case only needed a single "featured post" so I just had 1 ID to look for (no second loop, just a simple {% if %} match case).

 

Good luck!

Reply
0 Upvotes
Top Contributor

this looks great - I'll give this a go and let you know how I get on.

 

I made some changes to the recent posts by topics code so that it can have a cross sell advert/cta inserted in to the loop as well as a featured post, with the topic listing remoing the featured post item from the topic list.

 

 

Reply
0 Upvotes
Top Contributor

@mgrubbsI got this work, thanks for your help on this.

 

I made a few minor changes, I noticed there was no way to set a null value and also the ordering of the choices was by recent postsrather than choice1, 2, 3...

 

I've set up default variables for the limit and a null/please select choice.

In the getBlogId macro, I've set a unless condition so the loop runs as long a the search value doesn't equal the blog_list_default value.

 

{# Get 100 most recent posts... replace commas because it will break the comma-separated choice list #}

{% set blog_list_limit = 100 %}
{% set blog_list_default = 'Please select' %}

{% macro getBlogs() %}
    {% set blog_list = blog_recent_posts('default', blog_list_limit) %}
    {{ blog_list_default }},
    {% for blog_post in blog_list %}
        {% if loop.last %}
            {{blog_post.name|replace(","," ")}}
        {% else %}
            {{blog_post.name|replace(","," ")}},
        {%endif%}
    {% endfor %}
{% endmacro %}

{# Get the blog post ID  #}
{%- macro getBlogId(search) -%}
    
    {% set blog_list = blog_recent_posts('default', 100) %}
    {% unless search == blog_list_default %}
        {% set found = 0 %}
        {% for blog_post in blog_list %}
        
            {% if search|lower|urlencode == blog_post.name|replace(","," ")|lower|urlencode && found == 0 %}
                {{blog_post.id}}
                {% set found = 1 %}
            {% else %}
            {% endif %}
            
            {% if (loop.last && found == 0)  %}
                {{blog_list[0].id }}
            {% endif %} 
       
        {% endfor %}
    {% endunless %} 
{%- endmacro -%}

{% set postOptions = getBlogs() %}

{% choice "post_choice1" label='Choice 1', value='{{ blog_list_default }}', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice2" label='Choice 2', value='{{ blog_list_default }}', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice3" label='Choice 3', value='{{ blog_list_default }}', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice4" label='Choice 4', value='{{ blog_list_default }}', choices='{{postOptions}}' export_to_template_context=True %}

{% set post1 = getBlogId(widget_data.post_choice1.value) %}
{% set post2 = getBlogId(widget_data.post_choice2.value) %}
{% set post3 = getBlogId(widget_data.post_choice3.value) %}
{% set post4 = getBlogId(widget_data.post_choice4.value) %}

{% set choices = [post1,post2,post3,post4] %}

 

 

I've switch the for loops so the choices looped first before looping through recent posts. I'm not sure of the performance impact this has.

 

 

<ul>
{% set recent_posts = blog_recent_posts('default', 100) %}
{% set found = 0 %}
{% for choice in choices %}
    {% for post in recent_posts %}
		{% if choice is string_containing post.id %}
            {% set my_post = blog_post_by_id(post.id) %}
            <li> {{ post.id }} - <a href="{{ my_post.absolute_url }}">{{my_post.title}}</a></li>
		{% endif %}
	{% endfor %}
{% endfor %}
</ul>

 

Thanks again.

 

Reply
0 Upvotes
Highlighted
Regular Contributor

@matttunney -- Glad to see it's working out for you! Good adaptations, it's a good feeling when you can get these sorts of things working for your specific use cases eh?

 

Best of luck on future enhancements!

Reply
0 Upvotes
New Contributor

@mgrubbsIs there a way to make the first 4 posts automatically show up as the four most recent posts? With the code above, they all show up as the same most recent post. 

 

For example:

 

 {% choice "post_choice1" label='Recent Blog 1', value='{{Most Recent}}', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice2" label='Recent Blog 2', value='{{Most Recent}}', choices='{{postOptions}}' export_to_template_context=True %}
{% choice "post_choice3" label='Recent Blog 3', value='{{Most Recent}}', choices='{{postOptions}}' export_to_template_context=True %}

{% choice "post_choice4" label='Recent Blog 4', value='{{Most Recent}}', choices='{{postOptions}}' export_to_template_context=True %}

 

I'd like to change post_choice1's value to the first most recent, post_choice2's to the second most recent, and so on. That way, once I apply these edits to the template I don't have to immediately go back and select my desired posts on every past blog post. 

Reply
0 Upvotes