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
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.
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.
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();
}
});
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.
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?