Linking a Vue file with Django template - django

I have a Django project contains multiple templates like this:
<body>
<div>
<ul>
<li>
<a href="#">
customers
</a>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2"></script>
<!-- place project specific Javascript in this file -->
<script src="{% static 'js/project.js' %}"></script>
<script>
{% include 'vue_dashboard.js' %}
</script>
</body>
the vue_dashboard.js file is the following
var app = new Vue({
el: '#vue_app',
delimiters: ["{(", ")}"],
data: function () {
return {
selected: 'group',
}
},
methods: {
change_selected: function (type) {
this.selected = type;
},
}
Now, I'm trying to use this vue method inside my <a> tag for example like this:
<a href="#" onclick="change_selected(type='customers')">
customers
</a>
then inside some other div obtain the value of the selected variable in the data section:
<div>
{{selected}}
</div>
I've also tried:
{% verbatim %}
{{ selected }}
{% endverbatim %}
and few other things, I know I'm using it wrong, but what's the right way to do so? I'm not even sure if my template can communicate with the vue file like this

Change
<a href="#" onclick="change_selected('customers')"> <!-- removed type= -->
customers
</a>
this should work with verbatim but you can also change delimiters in vue.js like following
delimiters: ["{(", ")}"],
which you did but didn't change {{ to {( so please change like this:
<div>
{( selected )} // <= change here
</div>

The first problem was like #ashwin said with the brackets, the other one was that the Vue app closing brackets were missing, also onclick doesn't work, I replaced it with #click, then everything was okay

Related

Fetch and iterate through items in jinja amp

I'm using AMP and Jinja to fetch some data and its not working. I have this example
<div>
<amp-render src="amp-script:dataFunctions.fetchData" layout="fixed-height" height="52">
<template type="amp-mustache">
{% for user in users %}
<div>
<h3>
{{user.name}}
</h3>
</div>
{% endfor %}
</template>
</amp-render>
<amp-script id="dataFunctions" script="fetch-data-script" width="52" height="52" data-ampdevmode>
</amp-script>
<script id="fetch-data-script" type="text/plain" target="amp-script">
function fetchData(index) {
return fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(findContinentsData)
}
function findContinentsData(json) {
console.log(json)
return json
}
exportFunction('fetchData', fetchData);
</script>
</div>
This is what my console returns
I cannot make it work even with different data samples. What can be the error here?

Why doesn't the curly braces work for a Vue app within a Django template?

Basically, Im trying to integrate Vue with Django. I have the following template:
<!DOCTYPE html>
<html>
<head>
<title>Django Vue</title>
</head>
<body>
{% verbatim %}
<div id="components-demo">
<button-counter></button-counter>
</div>
{% endverbatim %}
<!-- Vuejs -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- App -->
<script>
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: `
<button v-on:click="count++">You clicked me {{ count }} times.</button>
`
});
// App definition
new Vue({ el: '#components-demo' });
</script>
</body>
</html>
Everything is very simple, CDNs are used, not webpack. The component shows up, but the count does not. In other words, the curly braces are not functioning properly within my template. Why is that? I have the verbatim tag up and running.
It looks like this:
Any help?
You didnt wrap the {{count}} with a {% verbatim %} tag, which means {{count}} is being interpreted by Django, not by Vue (you should be able to see that this is the case if you inspect the template that is being rendered).
This should work:
<!-- App -->
{% verbatim %}
<script>
// Define a new component called button-counter
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: `
<button v-on:click="count++">You clicked me {{ count }} times.</button>
`
});
// App definition
new Vue({ el: '#components-demo' });
</script>
{% endverbatim %}
The {% verbatim %} tag you used is not really necessary, because the reason you want to use it (in this case) is because both Django and Vue use the same mustache {{}} syntax, which is causing the conflict. This means you should use {% verbatim %} only if there would otherwise be a conflict of syntax (for example, the mustache syntax).

Impossible to replace content in tag <ul></ul>

I have html content like this
<div class='.desc_html_aff'>
sdsdfdfdgdsg
<ul class="pi_ul">
<li>abc</li>
<li>def </li>
<li>ererefe </li>
</ul>
wfwfwsfgdhfhfhdf
dgdfhfj
</div>
I woudl like te replace content of <ul> by '!!'
here jquery which dont work
var desc_aff=$('.desc_html_aff').html().replace(/<ul(.*?)>(.*?)<\/ul>/gi,"!!")
I really cannot see what I'm doing wrong, any ideas?
Please help, thanks
The HTML string that you want to transform contains newline characters, which aren't matched by .*?. You can use [\s\S]*? instead:
var desc_aff=$('.desc_html_aff').html().replace(/<ul(.*?)>([\s\S]*?)<\/ul>/gi,"!!");
console.log(desc_aff);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='desc_html_aff'>
sdsdfdfdgdsg
<ul class="pi_ul">
<li>abc</li>
<li>def </li>
<li>ererefe </li>
</ul>
wfwfwsfgdhfhfhdf
dgdfhfj
</div>

Change DIV class on click action Ember

I want to change the DIV class base on CLICK action. I am trying to make a floating sidebar like this http://startbootstrap.com/templates/simple-sidebar.html
This demo has only three lines of code for toggle-ing the class.
<script>
$("#menu-toggle").click(function(e) {
e.preventDefault();
$("#wrapper").toggleClass("active");
});
</script>
I want to achive same thing but in ember way. Below is my HTML code:
<div id="wrap">
<div class="pull-left" id="main_menu">
<ul class="list-group">
<li class="list-group-item">{{#link-to "selectImage"}}<h4>Choose Picture</h4>{{/link-to}}</li>
<li class="list-group-item">{{#link-to "message"}}<h4>Write Message</h4>{{/link-to}}</li>
<li class="list-group-item"><h4>Account info</h4></li>
<li class="list-group-item"><h4>Recent Orders</h4></li>
<li class="list-group-item"><h4>How to</h4></li>
<li class="list-group-item"><h4>FAQ</h4></li>
</ul>
</div>
<!-- Begin page content -->
<div class="container" id="page_content">
{{outlet}}
</div>
<!-- End page content -->
</div>
</script>
<script type="text/x-handlebars" id="cards/index">
<h1>
<button class="pull-left btn btn-default" data-target="#main_menu" {{action 'changeClass'}}>
<img src="images/icons/menu_tablet.png" class="main_menu"/>
</button>
</script>
Now I do not know how can I use the action to change the class in WRAP div. I will really appreciate any help regarding this issue.
You can add the action handler within the controller for cards/index
Controller = Ember.ObjectController.extend({
actions: {
changeClass: function() {
// Run logic here
}
}
})

Customize count list

I have this code I'm using to generate a list of records categorized into year, make, series, body style, and color for vehicles. I'd like to customize this further this way:
for the year, I want to have only up to 2004 being individual...the rest will fall under other i.e. 2009, 2008, 2007, 2006, 2005, 2004, Other.
for the make, I want to display the six makes with the highest popularity...there's a field in the model I'm using to assign the popularity of a make with a value of primary (highest), secondary or tertiary. The rest will fall under Other.
For the body style and color, I want to have the items having less than 3 records falling under Other.
My code is as below:
year_count = vehicle_query.order_by(
'-common_vehicle__year__year').values('common_vehicle__year__year').
annotate(count=Count('id'))
make_count = vehicle_query.order_by(
'common_vehicle__series__model__manufacturer__manufacturer').
values('common_vehicle__series__model__manufacturer__manufacturer').
annotate(count=Count('id'))
style_count = vehicle_query.order_by(
'common_vehicle__body_style__style').values
('common_vehicle__body_style__style').annotate(count=Count('id'))
colour_count = vehicle_query.order_by(
'exterior_colour__exterior_colour').values(
'exterior_colour__exterior_colour').annotate(count=Count('id'))
The bulk of what you're asking would probably better be handled outside of Django and instead by client-side javascript. To be clear, you could have portions handled by Django, but it would be cleaner not doing so. There are benefits to doing it this way:
Your Django template code stays cleaner
It will degrade nicely
You can later update the interface (change the javascript) and not have to worry about breaking the Django template
To handle this you could simply make a script that when given a <ul> tag (and maybe some arguments) will render that list in the format you're asking about.
Here's a simple example using jQuery. For this example, I'm going to wrap the functionality in a using a jQuery plugin pattern.
Say your django template outputs the following...
<ul>
<li>Chevy</li>
<li>Mazda</li>
<li>Honda</li>
<li>Ford</li>
<li>BMW</li>
</ul>
jquery.showmorelist.js
(function($) {
$.fn.ShowMoreList = function(visibleItemCount) {
// Wrap parent element
var parent = $(this).wrap('<div class="show-more-list"></div>').parent();
var ul = $(this);
// Enumerate children and hide extras
var counter = 0;
$(this).children().filter('li').each(function(){
counter += 1;
if (counter > visibleItemCount) {
$(this).hide();
$(this).addClass('hidden');
}
});
// Add link and bind click
var link = $('> Show More').click(function(){
$(ul).children().filter('.hidden').show();
});
$(parent).append(link);
}
})(jQuery);
page.html
<script type="text/javascript" src="jquery.showmorelist.js"></script>
<script type="text/javascript">
// On page load...
$(function() {
$('ul').ShowMoreList(4); // Shows only the first 4 items
});
</script>
This is a rather simple example, and it won't switch the "Show More" to "Hide More" but you should be able to figure that out from the context.
I managed to get a solution, so I thought it'd be good to update the answer here:
In the head section I have this:
<script type="text/javascript" src="{{ MEDIA_URL }}share/jquery/jquery.min.js"></SCRIPT>
<script type="text/javascript">
(function($) {
$(document).ready(function() {
//hide the additional content under "Display More"
$("div.additional_content").hide();
$("a.more").click(function () {
//show or hide the additional content
$(this).siblings("div.additional_content").toggle();
//change the attributes and text value of the link toggle
if($(this).text() == "Display Less"){
$(this).removeClass("less");
$(this).addClass("more");
$(this).html("Display More");
}else{
$(this).removeClass("more");
$(this).addClass("less");
$(this).html("Display Less");
}
return false;
});
});
})(jQuery);
Then wherever I want to reduce the number of available options I have this:
<div class="module_wrap">
<div class="module"> {% if year_count %} <strong>{% trans "Year" %}</strong> <br />
{% for item in year_count|slice:":6" %}
<ul>
<li> {{ item.common_vehicle__year__year }} ({{ item.count }}) {% if request.session.chosen_year %} <img src="{{ MEDIA_URL }}img/undo.gif" border="0" alt="Remove Year Filter" title="Remove Year Filter" /> {% endif %} </li>
</ul>
{% endfor %}
<div class="additional_content"> {% for item in year_count|slice:"6:" %}
<ul>
<li> {{ item.common_vehicle__year__year }} ({{ item.count }})</li>
</ul>
{% endfor %} </div>
{% if year_count|slice:"6:" %}Display More<br />
{% endif %} <br />
</div>
</div>
{% endif %}