Skip Navigation

[Résolu] Adding A Static Item To A View

Ce fil est résolu. Voici une description du problème et la solution proposée.

Problem:
The user has a grid view and would like to add a static element(add button) as the last grid cell when the view has results less than 18.

Solution:
The best/easy way is to hook into the view and test how many results it has, if less than 18, we'll inject a default post.
Inside the loop we'll create a condition to display a different content template for that default post.

A sample code to inject the post is:

add_filter( 'wpv_filter_query_post_process', 'jts_inject_draft_promo', 10, 3 );
  
function jts_inject_draft_promo( $query, $view_settings, $view_id ) {
    // replace this with the default/draft promo post idate
    $default_promo_id = 123;
     
    if ( $view_id == 784 ) {
        if ( $query_post_count < 18 ) {
            $default_promo = get_post( $default_promo_id );
            $query->found_post[] = $default_promo;
            $query->found_count = $query->found_count + 1;
        }
    }
     
    return $query;
}

A sample code to conditionally display a different Elementor template for the default post is:

[wpv-conditional if="( '[wpv-post-id]' eq '123' )" evaluate="false" ]
<div class="col-md-2">
    [elementor-template id="278"]
</div>
[/wpv-conditional]
[wpv-conditional if="( '[wpv-found-count]' lt '18' )" ]
    <div class="col-md-2">
    [elementor-template id="867"]
</div>
[/wpv-conditional]

Relevant Documentation:
https://toolset.com/documentation/programmer-reference/views-filters/#wpv_filter_query_post_process

https://toolset.com/documentation/user-guides/using-toolset-with-elementor-page-builder/create-templates-for-custom-post-types-with-elementor-and-toolset/

This support ticket is created Il y a 3 années et 9 mois. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

No supporters are available to work today on Toolset forum. Feel free to create tickets and we will handle it as soon as we are online. Thank you for your understanding.

Sun Mon Tue Wed Thu Fri Sat
9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 - - 9:00 – 13:00
14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 - - 14:00 – 18:00

Supporter timezone: Africa/Casablanca (GMT+00:00)

Marqué : ,

This topic contains 17 réponses, has 2 voix.

Last updated by Ed Il y a 3 années et 9 mois.

Assisted by: Jamal.

Auteur
Publications
#1656941

Ed

I have a view that displays a grid of up to 18 content items (CPTs) for particular location. If a particular location doesn't have 18 items (lets say they have only 10), I want the 11th item to be static and contain a link (for a user to add their content). If the particular location already has 18 items, that last, static item doesn't need to be displayed.

I'll need to provide access, so my next reply should be private. You'll need to see what I'm referring to.

#1656983

Jamal
Supporter

Languages: Anglais (English ) Français (Français )

Timezone: Africa/Casablanca (GMT+00:00)

Hello and thank you for contacting the Toolset support.

Your next reply will be private to let you share credentials safely. ** Make a database backup before sharing credentials. **

#1659853

Ed

Just following up...

#1659943

Jamal
Supporter

Languages: Anglais (English ) Français (Français )

Timezone: Africa/Casablanca (GMT+00:00)

Hello and my apologies for the late reply.

You can use conditionals inside of your wpv-index shortcodes with the wpv-found-count or wpv-items-count and probably wpv-loop-index.

As you are already using index=pad and index=pad-last, the easiest way I could come up with your current view is by generating multiple elements for purchasing the ad spot and removing all except the first one with a custom Javascript code. I updated your view with the following code:

		[wpv-item index=pad]
			[wpv-conditional if="( '[wpv-found-count]' lt '18' )" evaluate="false"]
			<div class="col-md-2"></div>
      		[/wpv-conditional]
      		[wpv-conditional if="( '[wpv-found-count]' lt '18' )"]
      		<div class="col-md-2 add-button"><h4>Button here</h4></div>
      		[/wpv-conditional]
		[wpv-item index=pad-last]
      		[wpv-conditional if="( '[wpv-found-count]' lt '18' )" evaluate="false"]
			<div class="col-md-2"></div>
      		[/wpv-conditional]
      		[wpv-conditional if="( '[wpv-found-count]' lt '18' )"]
      		<div class="col-md-2 add-button"><h4>Button here</h4></div>
      		[/wpv-conditional]
		</div>

Then I added this Javascript code to the view to remove the ad spots except the first one. Notice how I used the class "add-button".

jQuery(function($){
  $('.add-button').not(':first').remove();
})

You can have a different solution without using index=pad. But by using index=1 or 2, 3, 4, 5, and 6. And using a conditional on the wpv-loop-index with the possible values. For example when index=2, the conditional will only apply if wpv-found-count equals 2, 8, or 14(index+n*6).
I hope this gives you an idea. Let me know your feedback.

#1659955

Ed

Thanks, Jamal. I saw the adjusted view after I posted the follow-up.

This isn't really the solution I was looking for. I can see the static item on Los Angeles, California, but there are three instead of one (I removed the "button" code and added my Elementor template). hidden link

Locations with NO ads don't show anything (not even the static item). hidden link

#1659969

Ed

So, I wasn't able to see the jquery code, so I added it to the view. It does remove the last two instances of the static item, leaving only one (the way I want it to). I just need to get that same static item ([elementor-template id="867"]) to display when there are NO ads (no items found).

#1660001

Jamal
Supporter

Languages: Anglais (English ) Français (Français )

Timezone: Africa/Casablanca (GMT+00:00)

I added the following code to the view and it removes the additional ad spot elements:

jQuery(function($){
  $('.add-button').not(':first').remove();
})

Without Javascript code, the only way I think of requires to use a number on the index and dropping index=pad and index=pad-last.
Then inside each index, we can use a similar condition, one evaluated to true, and the second to false. The condition this time should be on the wpv-loop-index on its possible values. For example for index=1:

[wpv-item index=pad]
    [wpv-conditional if="( ('[wpv-loop-index]' eq '1') OR ('[wpv-loop-index]' eq '7') OR ('[wpv-loop-index]' eq '13') )" evaluate="false"]
   the content template
    [/wpv-conditional]
    [wpv-conditional if="( ('[wpv-loop-index]' eq '1') OR ('[wpv-loop-index]' eq '7') OR ('[wpv-loop-index]' eq '13') )"]
    the ad spot content template
    [/wpv-conditional]

I hope this makes sense. Let me know if you have any questions about it and I can fix the view again.

#1660007

Ed

I've added a few more ads to Los Angeles, California (for a total of 6 ads). The static item fails to show on the next row (position 7 of 18 or position 1 of row 2).

#1660069

Ed

I also can't understand why the static template doesn't show for cities with no ads (no-items-found). I can get a text string to display, but not the Elementor template.

#1660363

Jamal
Supporter

Languages: Anglais (English ) Français (Français )

Timezone: Africa/Casablanca (GMT+00:00)

I also can't understand why the static template doesn't show for cities with no ads (no-items-found). I can get a text string to display, but not the Elementor template.

This is probably an expected behavior from Elementor templates! If no post is passed to the template, nothing is rendered. Because the "Place ad" template type is page, I assume that Elementor expects to have a page or at least a custom post(page is a custom post type), but nothing is passed to it. I searched online on how to display static content designed with Elementor, but I could not find any. Or maybe this is another bug/issue. We can focus on it after finding a way for the general use case.

For the general use case, I discussed an option with the team and it may be a good lead, we can inject a default post into the view results when the view has less than 18 elements, and with only one condition on the default post id, we can show one of the Elementor templates. Example code can be found here https://toolset.com/documentation/programmer-reference/views-filters/#wpv_filter_query_post_process

None of us has tested this, so I wonder if you can allow me to take a copy of your website and check it locally, or if you can provide FTP access and let me check it? In that case, just update the previous credentials with FTP access or add them to your next reply.

#1660405

Ed

The site is not a production site. I have a fairly recent backup. Do whatever you need to do (as long as I'm able to see what you did).

#1660421

Ed

Jamal,
At the bottom of this page (https://toolset.com/documentation/user-guides/using-toolset-with-elementor-page-builder/create-templates-for-custom-post-types-with-elementor-and-toolset/), it says the following:

"Also, do not insert an Elementor Template into a View’s Loop Item or Content Template. If you need to use an Elementor Template in the Views Loop, add it directly within the wpv-loop tags. At the same time, make sure that the posts in the Views Loop are not using Content Template for styling."

I honestly can't make out what that means. I'm not using a Content Template. That much I know.

#1660439

Jamal
Supporter

Languages: Anglais (English ) Français (Français )

Timezone: Africa/Casablanca (GMT+00:00)

Please add the following code to your theme's functions.php file, hopefully, it will inject a default post into the view results. Replace the id of the default post (id 1, with the id of a draft promo post). Then check if it works.

add_filter( 'wpv_filter_query_post_process', 'jts_inject_draft_promo', 10, 3 );
 
function jts_inject_draft_promo( $query, $view_settings, $view_id ) {
	// replace this with the default/draft promo post idate
	$default_promo_id = 123;
	
	if ( $view_id == 784 ) {
		if ( $query_post_count < 18 ) {
			$default_promo = get_post( $default_promo_id );
			$query->found_post[] = $default_promo;
			$query->found_count = $query->found_count + 1;
		}
	}
    
	return $query;
}

After that, there will be no need to handle different index, just enough to wrap your columns in a row and one condition on the post id:

                [wpv-conditional if="( '[wpv-post-id]' eq '123' )" evaluate="false" ]
			<div class="col-md-2">
				[elementor-template id="278"]
			</div>
      		[/wpv-conditional]
      		[wpv-conditional if="( '[wpv-found-count]' lt '18' )" ]
      			<div class="col-md-2">
				[elementor-template id="867"]
			</div>
      		[/wpv-conditional]

To test this, myself, on your server, I need FTP access, this will allow me to check the debug.log file and to be able to recover in case of an error in code. I simply can't write any line of code on your server without having FTP access.

#1660477

Ed

Jamal,
We must have both solved this, at the same time, in different ways! 🙂

It occurred to me to make a Default Promo post type, with the default ad info, and include it in the view, sorted last, by post type.

#1660493

Jamal
Supporter

Languages: Anglais (English ) Français (Français )

Timezone: Africa/Casablanca (GMT+00:00)

The code was erroneous, my mistake 🙂
I tested with the view that I have created previously this morning and the following code has successfully injected the default/draft post into both views:

add_filter( 'wpv_filter_query_post_process', 'jts_inject_draft_promo', 10, 3 );
  
function jts_inject_draft_promo( $query, $view_settings, $view_id ) {
    // replace this with the default/draft promo post idate
    $default_promo_id = 924;
	$views_ids = array(784, 918);
     
    if ( in_array( $view_id, $views_ids ) ) {
        if ( $query->found_posts < 18 ) {
            $default_promo = get_post( $default_promo_id );
			$query->posts[] = $default_promo;
			$query->found_posts = $query->found_posts + 1;
			$query->post_count = $query->found_posts + 1;
        }
    }
     
    return $query;
}

Then, I updated my view (#ID 918) with the following code, because it needs the columns to be wrapped inside a <div class="row">

	<wpv-loop wrap="6" pad="true">
		[wpv-item index=1]
		<div class="row ">
			[wpv-conditional if="( '[wpv-post-id]' eq '924' )" evaluate="false" ]
				<div class="col-md-2">[wpv-post-id] [elementor-template id="278"]</div>
      		[/wpv-conditional]
      		[wpv-conditional if="( '[wpv-post-id]' eq '924' )" ]
      			<div class="col-md-2">[wpv-post-id] [elementor-template id="867"]</div>
      		[/wpv-conditional]
        [wpv-item index=last]
			[wpv-conditional if="( '[wpv-post-id]' eq '924' )" evaluate="false" ]
				<div class="col-md-2">[wpv-post-id] [elementor-template id="278"]</div>
      		[/wpv-conditional]
      		[wpv-conditional if="( '[wpv-post-id]' eq '924' )" ]
      			<div class="col-md-2">[wpv-post-id] [elementor-template id="867"]</div>
      		[/wpv-conditional]
          </div>
		[wpv-item index=other]
			[wpv-conditional if="( '[wpv-post-id]' eq '924' )" evaluate="false" ]
				<div class="col-md-2">[wpv-post-id] [elementor-template id="278"]</div>
      		[/wpv-conditional]
      		[wpv-conditional if="( '[wpv-post-id]' eq '924' )" ]
      			<div class="col-md-2">[wpv-post-id] [elementor-template id="867"]</div>
      		[/wpv-conditional]
		[wpv-item index=6]
			[wpv-conditional if="( '[wpv-post-id]' eq '924' )" evaluate="false" ]
				<div class="col-md-2">[wpv-post-id] [elementor-template id="278"]</div>
      		[/wpv-conditional]
      		[wpv-conditional if="( '[wpv-post-id]' eq '924' )" ]
      			<div class="col-md-2">[wpv-post-id] [elementor-template id="867"]</div>
      		[/wpv-conditional]
		</div>
	</wpv-loop>

I'll let you do the same for your view, and then remove my view from the content template.

"Also, do not insert an Elementor Template into a View’s Loop Item or Content Template. If you need to use an Elementor Template in the Views Loop, add it directly within the wpv-loop tags. At the same time, make sure that the posts in the Views Loop are not using Content Template for styling."

This means that we have to put the Elementor template shortcode directly inside the loop and that it won't work on other places or inside a content template.

This ticket is now closed. If you're a WPML client and need related help, please open a new support ticket.