Django Templates with Vue - django

I'm trying to integrate vue-components into django-templates. The basic setup did work, but I'm stacked with a component which needs an import itself.
Here is the component (vue/dropdown.html):
<div id="app">
<template>
...
</template>
</div>
<script setup>
import { computed, ref } from 'vue'
import {CheckIcon, ChevronUpDownIcon} from '#heroicons/vue/20/solid'
const query =ref('')
const selectedPerson = ref(null)
...
var app = new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
message: 'Hello Vue!',
},
});
</script>
So, the 2 imports:
import {computed, ref} from Vue
import {CheckIcon, ChevronUpDownIcon} from '#heroicons/vue/20/solid'
are triggering the error in the browser's console:
Cannot use import statement outside a module
What is the proper way to use the imports?
I'm calling the dropdown.html from base.html:
<html lang="{{ LANGUAGE_CODE }}">
<head>...</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
{% include 'vue/dropdown.html' %}
</body>
</html>

I think this happens because vue cdn should be imported into dropdown.html.Please try this fix and let me know if it works.
Thank you

Related

How can I pass a variable via jinja to a litelement?

I'm using flask to serve this html file. It is using jinja to display the provided data from flask. I can tell that the data is there, but I'm not sure how to pass it to my lit element.
<head>
<meta charset="utf-8">
<title>title</title>
<script type="module" src="{{ bundle }}"></script>
<script>
var data = {{ data|tojson }};
</script>
</head>
<body>
User: {{ data.user }}
<app-home .user="${data.user}" ></app-home>
</body>
</html>
The jinja code User: {{ data.user }}, works as expected.
But, in the litelement (AppHome), user is undefined.
I tried a few different variations on the formatting like .user="{{data.user}}", but I haven't been successful in passing the data to the litelement.
Edit to add lit code
import { html, LitElement, property, customElement } from 'lit-element/lit-element.js';
#customElement('app-home')
export class AppHome extends LitElement {
#property({type: String}) user?: string;
render() {
return html`
<p>user: ${this.user}</p>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
'app-home': AppHome;
}
}
The litelement works as expected, and can even render the user if I fetch it separately.

Can't use vue.js from django

I introduced vuejs using webpack in django, but I can not use vue instances from django templates.
Looking at the chrome devtool, the transpiled js is loaded correctly, but shows {{message}}.
The following message is output on the console of chrome devtool.
TypeError: undefined is not an object (evaluating 'hasOwnProperty.call (it, key)')
ReferenceError: Can't find variable: Vue
This is my code.
main.js
import Vue from 'vue'
import App from './App.vue'
import vuetify from '#/plugins/vuetify' // path to vuetify export
window.Vue = require('vue');
Vue.config.productionTip = false
new Vue({
render: h => h(App),
vuetify,
}).$mount('#app')
html
{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Example</title>
</head>
<body>
{% verbatim %}
<div id="app">
{{ message }}
</div>
{% endverbatim %}
{% render_bundle 'main' %}
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
</body>
</html>
log(django)
django | [09/Jan/2020 11:22:58] "GET /vue/ HTTP/1.1" 200 374
django | [09/Jan/2020 11:22:58] "GET /static/webpack_bundles/main-ccb1054f18bba9ee992d.js HTTP/1.1" 304 0
urls.py
from django.urls import path
from .views import signupfunc, loginfunc, listfunc, logoutfunc, vuefunc
urlpatterns = [
path('signup/', signupfunc, name='signup'),
path('login/', loginfunc, name='login'),
path('list/', listfunc, name='list'),
path('logout/', logoutfunc, name='logout'),
path('vue/', vuefunc, name='vue'),
]
vies.py
<snip>
def vuefunc(request):
return render(request, 'vue.html')
This might be a dumb question, but are you importing your main.js file from your template? It would look something like this:
<script src="{% static 'js/main.js' %}"></script>
Also, just as an aside, I use Vue with django and always list my own delimiter in the Vue code so I don't have to put {% verbatim %} tags around every variable. It looks something like this:
var app = new Vue({
el: '#app',
delimiters: ['${', '}'],
data: {
message: 'Hello Vue!'
}
})
and you can obviously pick whichever delimiters you want.

Django Vuejs -- Using Axios - Issue in redering Data

I am trying to use VueJs inside my Django Framework ( Django as Backend) and Vuejs as Front-End. However, I am very new with axios, which I found more easier to use with VueJS Front-End. On integrating all togetherr, I didn't see anything coming up but I can see that my code is loop through the data using vueJS Developer Tools.
index.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>The greatest news app ever</title>
</head>
<body>
<div id="app">
<template v-for="post in posts">
<p> Hello - {{ post.title }}</p>
</template>
</div>
<script src="{% static 'vue/vue.js' %}"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="{% static 'vue/app.js' %}"></script>
</body>
</html>
app.js
new Vue({
el: '#app',
data: {
posts: []
},
methods:{
getPost: function(){
var self = this;
let url = "http://127.0.0.1:8000/api/allpost/";
axios.get(url).then((response) => {
this.posts = response.data
}, (error) => {
console.log(error);
});
}
},
mounted: function() {
this.getPost();
}
});
The Output of the code
{{ post.title }} has been the problem rendering the Data into Django Page, because Django also make use of this {{ }}. However, in a situation where someone is rendering the page with VueJS Server is doesn't apply. then, remember to add this:
delimiters: ['[[', ']]'],
<li v-for="post in posts" v-bind:key="post.id">
[[ post.title ]] <br/>
[[ post.body ]]
<hr/>
<li>
new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
posts: []
},
methods:{
getPost: function(){
var self = this;
let url = "http://127.0.0.1:8000/api/allpost/";
axios.get(url).then((response) => {
this.posts = response.data
}, (error) => {
console.log(error);
});
}
},
mounted: function() {
this.getPost();
}
});

Component not rendering when using vue-template

I have the following...
main.vue
<template>
<div>
<header></header>
</div>
</template>
<script>
export default {}
</script>
header.vue
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
data: () => {
return {
message: 'Dashboard'
}
}
};
</script>
main.js
import Vue from 'vue';
import Header from './header.vue'
import App from './main.vue'
Vue.component("header", Header);
new Vue(App).$mount('#km-viewport')
But when I run this the header component is never rendered. What am I missing? Does using the vue-template webpack plugin require something special here?
I have looked at a couple similar stack overflows and I have tried to use components: { Header } instead but that still doesn't work.
I also tried...
main.vue
<template>
<div>
<header></header>
</div>
</template>
<script>
import Header from './header.vue'
export default {
components:{
"header": Header
}
}
</script>
header.vue
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
data: () => {
return {
message: 'Dashboard'
}
}
};
</script>
main.js
import Vue from 'vue';
import App from './main.vue'
Vue.component("header", Header);
new Vue(App).$mount('#km-viewport')
Yours is a frequent problem:
[Vue warn]: Do not use built-in or reserved HTML elements as component id: name
In your case <header> is a reserved HTML element.
The same happens to <main>, <article> and so on.
Solution: Rename your header component to other name.
Example (I renamed header to header2):
main.vue
<template>
<div>
<header2></header2>
</div>
</template>
<script>
import Header from './header.vue'
export default {
components:{
"header2": Header
}
}
</script>
header.vue
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
data() {
return {
message: 'Dashboard'
}
}
};
</script>
Bonus: Don't use arrow functions as in data: () => {, that will give you problems. Use like data() {. This rule applies to methods, computeds, watchers and all other Vue instance options.

django webpack loader setting to load css

It works when I set up like below. I am using django-webpack-loader
index.html
{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Jayground</title>
{% render_bundle 'main' 'css' %}
</head>
<body>
<div id="react-app"></div>
{% render_bundle 'main' 'js' %}
</body>
</html>
Header.js
import styles from './header.css';
export default class Header extends React.Component {
render(){
<div className="header">
hello
</div>
}
}
webpack.config.js (I made styles.css separately and then load css file in html separately so that className="header" works.)
config.plugins = config.plugins.concat([
new ExtractTextPlugin('styles.css'),
]);
config.module.rules.push(
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader'
})
}
)
According to what I understood, code below should work too. If I don't separate css file by using ExtractTextWebpackPlugin, bundle js file have css information in it like this.
exports.push([module.i, ".header {\r\n background-color: blue;\r\n}\r\n\r\n.extra {\r\n\tfont-size: 50;\r\n}", ""]);
css should be loaded properly.
Header.js
import styles from './header.css';
export default class Header extends React.Component {
render(){
<div className={styles.header}>
hello
</div>
}
}
webpack.config.js
config.module.rules.push(
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
)
Do I miss something to work properly?