Change css class based on url slug in OctoberCMS - html

So I am trying to work on a OctoberCMS theme for my own project. The goal is to have the whole navigation header in a different color, based on the page the user is on. Seems pretty simple but I was after hours of trying still not able to manage.
So my idea was to add a different css class based on the page the user is on. For https://example.com/foo/bar a class like this should be showing: navbar-foo
I found OctoberCMS Twig has a option called this.param.tab which should return exactly "foo", so I thought of this:
{% if this.param.tab == 'foo' %}
<nav class="navbar-foo">
{% if this.param.tab == 'bar' %}
<nav class="navbar-bar">
And so on. The thing is, that would take up a lot of space and I didn't think it was that clean of a way. Also the class would need to be on multiple elements which would kind of make it a bit unreadable. So i thought I'll just solve it like this:
{% set slug = this.param.tab %}
<nav class="navbar-{ slug }">
<div class="navbar-menu-{ slug }
This didn't work. First I thought it didn't work because I didn't insert the twig right for it to be counted as a string in the html. The other thing I thought I did wrong was that this.param.tab returns an Array and not a string. So i tried different ideas to insert it into the class attribute and change it from array to string when I realised, that this.param.tab was empty.So I tried wrapping it into a div and just display it like that. But that just turned out empty. I tried to {{ dump(this.param.tab) }} which also turned out empty.
So it seemed to me that this.param.tabactually did not return anything. As the code is in the header.htm I thought maybe it needed to be in the main called file, as the header.htm is just a partial that gets inserted. So I tried the layout.htm and I tried home.htm (layout is the file, that defines the layout of the page, where the partials/page are inserted and home.htm is the file that actually contains the slug and the other code of the page the user is visiting). But that didn't do anything either.
So i'm not entirely sure what is wrong here. Does this.param.tab even actually work? or is there a better way I should do this?
If you need additional information ask, but I thought it won't matter because it is just a basic October setup and the theme is just twig, javascript and scss.

if you just need url for your condition you can do like this
{% set slug = this.page.settings.url|replace({'/': '-'} %}
<nav class="navbar{{ slug }}">
<div class="navbar-menu{{ slug }}
Now if you set your url = "/foo/bar" your class name will be navbar-foo-bar, if you set your url = "/test" your class name will be navbar-test, if you set your url = "/bla/ok/test" your class name will be navbar-bla-ok-test.
with params
you need to set your url to => /foo/:tab and then you can get tab value in to {{ this.param.tab }}
so once you set url like that then you can get values like this
if you use url http://example.com/foo/bar -> {{ this.param.tab }} will be foo
<nav class="navbar-{{ this.param.tab }}"> -> will be -> <nav class="navbar-foo">
if you use url http://example.com/foo/test -> {{ this.param.tab }} will be test
<nav class="navbar-{{ this.param.tab }}"> -> will be -> <nav class="navbar-test">
if any doubts please comment.

Related

Dynamic Display in Base HTML using DJango

I am new to DJango and i am creating a Website. I have created a base HTML page with a NAV bar which will be used across all pages. I want to display the message "Welcome 'username'" as the first line across all pages.
I had written the following code in views.py
def getusername(request):
uname=request.getusername()
return render(request,'main.html',{'uname':uname})
in the main.html after defining the title and nave bar, i have the following html code
<span class="label label-default">Welcome{{uname}}</span>
When i run this code, I am able to view the NavBar in all pages tat extends the base page(main.html)
but the welcome message does not fetch the username.
I have configured the following in urls.py
path("", views.getusername,name='getusername')
Note: Even when i hardcode a string to be returned from views.py, the string is not displayed as part of the welcome message
In every template you have access to user object.
You can check if user is authenticated:
{% if user.is_authenticated %}
Welcome, {{ user.username }}
{% else %}
# show register or(and) login button
{% endif %}

How to customize ckan header site navigation tabs

I would like to add extra header site navigation tabs to the default ones.
I have tried working with the solution given here but it is not working for me. I am getting Exception: menu itemapicannot be found error
This is my plugin.py code
import ckan.plugins as plugins
import ckan.plugins.toolkit as toolkit
class ApiPlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm):
plugins.implements(plugins.IRoutes, inherit=True)
def before_map(self, m):
m.connect('api', #name of path route
'/api', #url to map path to
controller='ckanext.kimetrica_theme.controller:ApiController', #controller
action='api') #controller action (method)
return m
This is my header.html code
{% ckan_extends %}
{% block header_site_navigation_tabs %}
{{ h.build_nav_main(
('search', _('Datasets')),
('organizations_index', _('Organizations')),
('group_index', _('Groups')),
('about', _('About')),
('api', _('api'))
) }}
{% endblock %}
And this is my controller.py code
import ckan.plugins as p
from ckan.lib.base import BaseController
class ApiController(BaseController):
def api(self):
return p.toolkit.render('api.html')
I expect to have the api menu work like the rest of the menu do. I also have my template(api.html) in place
Based on what you posted it looks like you haven't setup plugins.implements(plugins.IConfigurer, inherit=True) to register your new template. Try referencing this extension as an example. https://github.com/ckan/ckan/blob/2.8/ckanext/stats/plugin.py for setting up a new page.
You're on the right track for the menu.
Also what version of CKAN are you using? You may want to pswitch this to a flask blueprint. Like this https://github.com/ckan/ckan/blob/2.8/ckanext/example_flask_iblueprint/plugin.py
If you are using 2.9 (in alphha) check this issue out and the comments ckan 2.9.0 iroute before_map not invoking custom controller
I solved this question by using ckanext-pages extension This extension allows you to add simple static pages and blogs and edit their contents.
I solved it by creating a new HTML file for the header, e.g. header_foo.html. Additionally, you have to change the page.html:
…
{%- block header %}
{% include "header_foo.html" %}
{% endblock -%}
…
In the same way, you can hide the navigation tabs.

Using 'this' keyword in Angular component's template

Let's say we have a prop variable in the component class and we use it via interpolation in the template (stackblitz demo):
component class:
#Component({...})
export class AppComponent {
prop = 'Test';
...
}
template:
<p>{{ this.prop }}</p>
<p>{{ prop }}</p>
Why in Angular it's possible to use this keyword in templates without any warnings/error (even in AOT mode)? What's behind it?
Edit
According to the remark in the answer: this refers to the component itself for which the template was rendered. But I can also create a template variable and access to it using this:
<input #inp> {{ this.inp.value }}
In this case we don't have an inp variable in the component class and I still get the access to it using {{this.inp...}}. Magic?
I don't think somebody can give a very much exact answer here (maybe somebody from Angular CLI team), however the outcome I came to is that the component renderer fully ignores this keyword in the places where it seems valid (with some exceptions).
Proof
<input #heroInput value="0">
This prints the component JSON without heroInput: {{ this | json }}
<input #heroInput value="0">
This prints 0: {{ this.heroInput.value }}
<div *ngFor="let val of [1,2,3]">
<input #heroInput [value]="val">
Overrides heroInput with current value: {{ this.heroInput.value }}
</div>
This prints 0: {{ this.heroInput.value }}
One can assume from the above that this is similar to AngularJS (angular 1) scope, where the scope contains the component properties.
It does not explain why heroInput is not listed in this | json still.
However the following is totally broken:
{{ this['heroInput'].value }}
It gives an error: cannot get value of undefined. It should, not, it must work, unless (the only explanation) this is just ignored in every case but
{{ this | json }}
where it refers to the component, because this is the only way to debug the whole component object from the template. Maybe there are some other exceptions, still.
Updated stackblitz
this refers to the component itself for which the template was rendered. On the template you can access only members of the component. This means that this is implicitly added to each property which you use in the template.
This two accesses are the same - the 2nd one implicitly use this in front of it.
<p>{{ this.prop }}</p>
<p>{{ prop }}</p>
The same is when you use this in the component. When you want to access prop in the component you need to prefix it with this.prop to inform that you are accessing property of the component, not a local variable.
I felt we can't get a proper explanation on this but,
I went through a case where i will be creating the members of the component dynamically.
In here it might go wrong, if i don't use this.member (In my case it was actually this[member]).
Create a member in component like,
this.members(prop=> this[prop]={})
Usage in template will be like,
{{this[prop]}} will give expected result.
{{prop}} will not give expected result because
it will print value of list.

Jekyll variable for all posts

I would like to set up a variable to share across all posts to set up the expected location of images so I can do this:
![My sweet image]({{ post.images }}/sweet-image.png)
Which I eventually want to emit:
{{site.baseurl}}/images/posts/{{page.date | date: '%Y' }}
I've tried a bunch of things and cant seem to work out how to get anything to show up on the post object (for all pages).
Things I've tried (Ive ignored the variables component to try to make it simpler for now):
in post.html layout:
---
layout: default
b: 'bananas'
---
{% assign a = 'apples' %}
And then in a post:
{{a}}{{b}}
{{post.a}}{{post.b}}
None of these options seem to do anything. Im guessing im putting it in the wrong place or doing it wrong but im not too sure where I should be putting post-scoped variables.

Jekyll - Next and previous links with different categories

I am using Jekyll to build a blog, I managed to successfully implement a Next and Previous links on my layouts pages (using this answer). I've added several categories (using this answer) and each page iterates through the proper categories displaying only what I want them to.
My only problem now is that Previous and Next buttons still iterate through all the posts regardless of what category they are in.
This is the code I used for the Next and Previous links on the bottom of the layout:
{% if page.previous %}
<span class="previous-link">
<a rel="prev" href="{{ page.previous.url }}">Previous Entry</a>
</span>
{% endif %}
{% if page.next %}
<span class="next-link">
<a rel="next" href="{{ page.next.url }}">Next Entry</a>
</span>
{% endif %}
Is there a way to make the Next and Previous buttons go to the next or previous post in the current posts' category?
After a bit of research. I found exactly what I was looking for on this blogpost - http://ajclarkson.co.uk/blog/jekyll-category-post-navigation/
Just needed to add a plugin to the _plugin directory and add this bit of code in it:
module Jekyll
class WithinCategoryPostNavigation < Generator
def generate(site)
site.categories.each_pair do |category, posts|
posts.sort! { |a,b| b <=> a}
posts.each do |post|
index = posts.index post
next_in_category = nil
previous_in_category = nil
if index
if index < posts.length - 1
next_in_category = posts[index + 1]
end
if index > 0
previous_in_category = posts[index - 1]
end
end
post.data["next_in_category"] = next_in_category unless next_in_category.nil?
post.data["previous_in_category"] = previous_in_category unless previous_in_category.nil?
end
end
end
end
end
And instead of using page.next.url and page.prev.url in the HTML, just use page.next_in_category.url and page.previous_in_category.url.
I hope this helps anyone experiencing the same issue.
The ajclarkson plugin for pagination within categories is a correct and useful solution if you are able to install plugins.
If you want to deploy to Github pages, you cannot use plugins.
I use this method to paginate within categories. This makes sure that a post from a different category will never show up:
{% if page.next and page.next.categories contains "blog" %}
Next Post
{% else if page.previous and page.previous.categories contains "blog" %}
Previous Post
{% endif %}
Be aware, this solution will not find a next post if it would have to skip over something from a different category. It avoids the worst (?) scenario, which is linking to something unintentional/not-really-a-post.