'Getting Value of Selected Nav Pill

I'm trying to make a pair of nav pills to choose between a graphical and a tabular output for a set of data and I can't seem to figure out how to grab the value of the nav pill. I defined the nav pills as follows:

<div class="col-md-2">
        <ul class="nav nav-pills nav-stacked">
            <li {% if type_display == 'charts' %}class="active"{% endif %}><a href="charts" class="text-primary"><i class="fa fa-fw fa-bolt"></i> Charts</a></li>
            <li {% if type_display == 'tables' %}class="active"{% endif %}><a href="tables" class="text-primary"><i class="fa fa-fw fa-calendar"></i> Tables</a></li>
        </ul>

and they render like this: enter image description here

How do I pass the selected nav pill back to django? I tried:

display_type = request.GET.getlist('charts')

I have next to no experience in HTML so any info would be awesome. Thank you!



Solution 1:[1]

I see my previous answer (below) might be a bit complicated in order to achieve what you want. Since you seem to use links in your page I would suggest the following:

Pass a parameter to your views using a correct urlpattern and links your views, like so:

template/html:

<div class="col-md-2">
        <ul class="nav nav-pills nav-stacked">
            <li {% if type_display == 'charts' %} class="active"{% endif %}><a href="{% url 'yourview' charts %}" class="text-primary"><i class="fa fa-fw fa-bolt"></i> Charts</a></li>
            <li {% if type_display == 'tables' %} class="active"{% endif %}><a href="{% url 'yourview' tables %}" class="text-primary"><i class="fa fa-fw fa-calendar"></i> Tables</a></li>
        </ul>

urlpattern in urls.py

urlpatterns = [
    path('yoururl/<str:choice>/', views.yourview, name='yourview'), # Django 2
    url(r'^yoururl/(?P<choice>\w+)/$',views.yourview, name='check yourview'), # Django 1.11 and previous
]

views.py

def yourview(request, choice):
    # In your view you can now access the choice. Like so:
    print(choice)

But this is all pretty basic Django stuff, something I guess you'd know already. And this would have Django reload the whole page, although this can also be combined with Ajax as I have done below. The way below prevents having to load a whole new page. The link style as used above can also be used in the code below, instead of using a form.

Please let me know if you have any questions.

Here follows a more complicated way, but it allows for the user to stay in the page

The way I'd do it is the following, although there might be better ways, as I am only programming since a few months now.

You could use a form of the radio button input type. I assume you know a bit about forms, since you work with Django.

Here you'll find more information on using forms (of radio input type) https://www.w3schools.com/html/html_forms.asp

But you don't want to see the radio buttons, I am sure you can hide them. This website might help you out with that (I am not sure this is page has the answer, but I am sure there is a pretty easy way to hide the radio buttons):

https://www.jotform.com/answers/22605-How-to-make-radio-buttons-invisible

I am not experienced with the 'nav pills' but I am quite sure you can display the nav pills as the content of the radio button options:

<input type="radio" name="gender" value="male" checked> <nav-pill-goes-here><br>

Hope this gives you another perspective.

Edit:

The downside is you normally need a submit button to send your info to the view (when working with forms), but you probably don't want an extra button in your page. You can get around this by using Ajax (with JavaScript/jQuery), but if you don't know how that works, it might take you some studying that, and that's probably not what you want. If f you do, I recommend checking out this tutorial:

https://simpleisbetterthancomplex.com/tutorial/2016/11/15/how-to-implement-a-crud-using-ajax-and-json.html

With ajax you can have the event of clicking one of the options have the post request be send to a view without leaving the page, but still have the view handle the input as you wish.

Example

Here i made an example. I've also tried hiding the radio buttons, but I'd need to do more research on how to do that and still being able to select the options. But this point to one possible solution. you only need to add the nav pills, hide radio buttons, and have the proper view to handle the logic.

Note that you need jQuery for this to work, which I loaded before the end of the </body> tag. Bootstrap 4 also uses jQuery, but it uses the slim version. You can replace the slim version with this version, although this version is 3.3.1, while bootstrap now loads 3.2.1, but I assume there are very little to no situations where this is a problem.

example html/template

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<form method="post" action="{% url 'offer:radio_test' %}" id="chart-table-form">
  {% csrf_token %}
  <input type="radio" name="radio-option" value="chart"> Chart<br>
  <input type="radio" name="radio-option" value="table"> Table<br>
</form>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script>
  $(function() {
    var form = $("#chart-table-form");
    document.getElementById("chart-table-form").addEventListener("click", function() {
      $.ajax({
        url: form.attr("action"),
        type: "post",
        data: form.serialize(),
        dataType: "json"
      });
      return false;
  });
});
</script>
</body>
</html>

views.py

def radio_test(request):
    if request.method == 'POST':
        print(request.POST.get("radio-option")) # This will return the value 'chart' or 'table' / have you access the radio button value
    return render(request, 'offer/radio_test.html')

Solution 2:[2]

$("ul.nav-pills > li > a").click(function() {tabSelected =  $(this).attr("value");});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mr Lister
Solution 2 Jakub Kurdziel