Override template only on specific page

Hello, I’ve been customizing my Discourse appearance in the theme’s custom field.
I use | script type="text/x-handlebars" data-template-name="components/categories-only" |
and similars to override some specific templates, is there any way to override it on only specific pages like homepage and use different code in sub-categories view for example? I am still quite new to Discourse, I am not even sure if its the correct way to do it in themes custom HTML/CSS (i know that i lose it on update) If someone could help me out with this, I would really appreciate it.


Just to clarify this bit first

This is not correct, you don’t lose your changes when you update if they’re made in a theme. They persist. The only way you lose your changes is if you directly edit the files on your server, which you obviously shouldn’t do.

Now, there is a certain amount of risk involved in overriding templates in that an update in core might mean that your changes are not compatible anymore and would need to be updated. If you’re fine with that risk then you can technically achieve what you’re asking for here.

To start, you need someway to distinguish when the user is on the homepage. In the case of the categories-only component one way is to check the searchContext. When you’re on a subcategory page, the search context is set to “category”. If there’s no search context, it means you’re on the homepage.

The way to pass that to your template is by adding something like this

<script type="text/discourse-plugin"
        version="0.8">
  const categoriesOnlyComponent = require('discourse/components/categories-only').default;
  categoriesOnlyComponent.reopen({
    isHomepage: function() {
      return !this.parentView.searchService.contextType
    }.property()
  });
</script>

and what that does is allows you to use isHomepage in the template for categories-only it returns true if there’s no search context which means you’re on the homepage. Otherwise, it returns false.

Next you need to copy over the default template like so

<script type='text/x-handlebars'
        data-template-name='components/categories-only'>
  {{#if categories}}
  ... rest of the template
  {{/if}}
</script>

and use isHomepage that we added. For this you need to use the handlebars {{#if}} helper. Essentially what you need is something like this

<script type='text/x-handlebars'
        data-template-name='components/categories-only'>
  {{#if categories}}
    {{#if isHomepage}}
      ... template for homepage only
    {{else}}
    ... rest of the default template if not on the homepage
  {{/if}}
</script>

You can now use whatever you want in the isHomepage section. You can edit it right there or you can create a new template for that section like so

<script type='text/x-handlebars'
        data-template-name='components/categories-only-homepage'>
  <h1>You're on the homepage!</h1>
  <p>
    Use this section to render the template for the categories-only component if the user is on the homepage.
  </p>
</script>

The last thing you need to do is to call that template as a partial in the categories-only template inside the isHomepage section like so

<script type='text/x-handlebars'
        data-template-name='components/categories-only'>
  {{#if categories}}
    {{#if isHomepage}}
      {{partial 'components/categories-only-homepage'}}
    {{else}}
    ... rest of the default template if not on the homepage
  {{/if}}
</script>

The result is that when you visit the homepage you’d see this

but the component in subcategories should remain unchanged.

This is optional but you might also be interested in looking at

because that’s the new recommended way to work on themes and avoid using script tags.

5 Likes

Amazing, thank you very much! Now I also kinda understand how to use text/discourse-plugin. I appreciate it a lot!

1 Like

Hey, I’d like to ask one more question.
Could you tell me how can i get the latest topic in specific subcategories? I can use category.latestTopic to get the latest topic of a category but I can’t use it for subcategories, any smart workaround for this? I would like to show the latest topic of a subcategory when i list the subcategories.