How can I move from a Svelte component to an HTML file using window.location.href?
I tried various combinations, but the HTML can't be found. Do I have to set up routing?
Folder Structure:
project
├── example.html
├── svelteProject
├── src
├── App.svelte
The most ideal thing would be to use Sveltekit. You could also try to create a full page iframe, not sure how you'd reference your HTML file though.
Summery
I'm creating Vue/Nuxt application by SPA mode.
To generate /.dist file, I execute nuxt generate
pages
├ index.vue
└ test.vue
I want to know how to redirect / to /test path by Nuxt.
What I tried
I tried middleware and module, but they do not work.
https://github.com/nuxt-community/redirect-module
One simple workaround is to use fetch hook in the index page to change rout to /test; Here is the code:
// index.vue
fetch() {
this.$router.push('./test');
}
I'm building an Electron app that needs to have multiple pages. I've looked at Vue Router (I'm already using Vue) as a routing system, but I'd like to store every page a a separate HTML file.
I've tried a couple of things:
Making an Ajax request to the page, then putting its contents into the route. When trying to navigate to the route, I got a route not allowed error.
Making an Ajax request to the page, then replacing the #app element's contents with the requested page. This caused the {{ template_things }} to stop working.
I'm open to using other routing systems, too. Vue Router just seemed the most convenient.
Thank you!
You could try out Nuxt.JS.
The big innovation of Nuxt.js comes with the nuxt generate command.
When building your application, it will generate the HTML for every one of your routes and store it in a file.
For example, the following file structure:
-| pages/
----| about.vue
----| index.vue
Will generate:
-| dist/
----| about/
------| index.html
----| index.html
There is an Electron starter app with Nuxt on GitHub
I've recently started on some social media web site using Django. Im using the default django template engine to fill my pages. But at this moment, I want to add javascript to make the site more dynamic. This means:
The header and footer is the same on each page. The header should have a dropdown menu, a search form that searches when you're typing.
My current django application has a base template that has the header and footer HTML, since every page should have this.
The site consists of multiple pages, think of index page, profile page, register page. Each of these pages have some common but also a lot of different dynamic components. For example the register page should have form validation on the fly, but the profile page doesn't need this. The profile page should have a status feed with infinite scrolling.
I want to use Vue to deal with the dynamic components, but I don't know how I should get started. The application should not be a SPA.
How should I structure the Vue code?
How should I bundle this. Using Gulp? Or maybe django-webpack-loader?
I should still be able to use the Django template tags, for example I want to be able to use {% url 'index' %} in the dropdown menu.
This looks like an opinion based question for which there is no clear answer.
You mentioned that you do not want the app to be a Single Page Application (SPA). If so, what is the motivation for using Vue? To handle user interactions within page?
Vue can work perfectly alright in non-SPA context. It will help you handle rich interactions within the page, like binding your data to drop-downs, forms, etc. But the real power of Vue comes out when you use it in SPA context.
For your case, I would recommend using Vue.js in standalone mode, where you can quickly define template within Vue components and write all your code easily in one javascript file.
Here is what you need: https://vuejs.org/guide/installation.html#Standalone
In "Vue.js standalone mode", There is no need for any webpack build system or vue-cli. You can build the app directly in your existing dev environment for django. gulp can optionally minify and bundle your javascript files normally, just like you do with your jQuery based apps.
Vue.js uses double curly braces {{..}} for templates, so it will not interfere with your django template strings.
All the jsFiddle examples for Vue.js run in standalone mode. That is precisely what you need at this moment. You may look at some of the recent questions with vue.js tag, find a sample jsFiddle and see how it is done.
For complex SPA apps, you need to build your Vue code separately from server side, test it thoroughly with dummy AJAX calls, build it for production and then drop the final production build into your server for end-to-end testing. This is something you can do in future.
I looked at this question and others a while back while looking to do pretty much what the OP was asking. Unfortunately, most of the information on Vue is given in an SPA context. However, as Evan You has often repeated, Vue is not opinionated and does not require usage within an SPA.
I'd like to share some of my findings and sketch out a possible approach to making Django and Vue work together. While an SPA is not required
I think the real power of Vue comes from its Components and that kinda pushes you towards a Webpack or similar approach, not simple standalone
mode in the html.
Also, just to be very clear: 90%+ of my the contents Django view code and templates remained exactly the same as before. Django doesn't particularly care that it's using webpack_loader and render_bundle. And even less that render_bundle has something to do with Vue. Between Django template blocks, verbatim tags and Vue slots, you get a lot of flexibility that allows you to leave most of your existing content alone.
Last, once your app is stable, you can disable the hotreload server on port 3000, run npm run build-production and use collectstatic to have your JS served via nginx/apache like any normal static content. So node runs as the occasional batch rather than as a service. Takes a bit of fiddling with Django's config, but well within reason.
Apologies, this is quite sketchy, don't expect working code as I am stripping so much out. But hopefully it'll give you an idea.
mysite/__full12_vue.html:
This is my base Vue-ify Django template that extends my existing Django base template, __full12.html.
assume that __full12.html defines all the general Django blocks, like {% block content %} and the like
(actually, there is a very important div with ID bme-vue so I've added this template at the end as well. )
I've added a Vue Component to display user messages.
And redefined the menu template to use Vue + Bootstrap dropdowns.
{% extends "mysite/__full12.html" %}
<!-- KEY: use this to hook up to https://github.com/ezhome/django-webpack-loader -->
{% load render_bundle from webpack_loader %}
{% block nav %}
<!-- uses Vue to setup Bootstrap dropdown menus -->
{% include "mysite/menu_vue.html" %}
{% endblock nav %}
{% block user_msg %}
<div class="row">
<div class="col-6">
<!-- uses Vue to display user messages -->
<bme-user-messages>
<div>THIS SHOULDNT APPEAR ON SCREEN IF VUE WORKED</div>
</bme-user-messages>
</div>
</div>
{% endblock user_msg %}
{%block extra_js_body_end%}
<!-- KEY this points Django Webpack loader to appropriate Webpack entry point -->
{% render_bundle bundle_name %}
{%endblock extra_js_body_end%}
webpack.config.development.js:
This is where you tell Webpack which JS to serve for the bundle_name you specify in the view.
How to configure Webpack is out of scope of my post, but I can assure you it was a real PIA. I started out with pip django-webpack-loader, then https://github.com/NdagiStanley/vue-django then Bootstrap 4 stuff. However, the end result is way more powerful than standalone, in my opinion.
/*
webpack config dev for retest
*/
config.entry = {
"main" : [
'webpack-dev-server/client?http://localhost:3000','../../static_src/js/index'],
// ....stuff..
//KEY: ONE entrypoint for EACH bundlename that you use.
"mydjangoappname/some_django_view" : ["../../static_src/js/mydjangoappname/some_django_view"],
"mydjangoappname/another_django_view" : ["../../static_src/js/mydjangoappname/another_django_view"],
// ....stuff..
}
// ....stuff left out...
mydjangoappname/some_django_template.html
Finally, we are ready to display some actual contents:
bme-nav-item and bme-tab-pane are 2 custom Vue components I use for Boostrap 4 tab navs and contents.
Django uses var settings= some-json-object to communicate instance-specific, rather than page-generic, data to Vue and JS
{% extends "mysite/__full12_vue.html" %}
<script>
// KEY: settings is provided by json.dumps(some_settings_dictionary)
// which your views puts into your RequestContext.
// this is how Django tells Vue what changes with different data, on the same view
var settings = {{settings | safe}};
</script>
{% block content %}
<!-- a button to run a Celery batch via a post command, url should probably come
from Django url reverse and be put into a Vue property...
-->
<button v-bind:data-url="url_batch" type="button" class="btn btn-block btn-outline-primary" #click.prevent="run_batch">
<!-- lotsa stuff left out.... -->
<ul id="tab-contents-nav" class="nav nav-tabs nav-pills">
<!-- *label* is using a Vue Prop and because there is no {% verbatim %} guard around it, Django will
inject the contents. {% urlrev xxx %} could be used to write to an 'url' prop. Ditto the conditional
inclusion, by Django, of a template if it's in the RequestContext.
-->
{% if templatename_details %}
<bme-nav-item link="details"
label="{{details_label}}" >
</bme-nav-item>
{% endif %}
<!-- lotsa stuff left out.... -->
<bme-tab-pane link="details">
<div slot="content">
<!-- KEY: Vue slots are incredibly powerful with Django. Basically this is saying
to Django : inject what you want in the slot, using your include, I'll tidy up afterwards.
In my case, this is a Bootstrap NavItem + NavTab
-->
{% if templatename_details %}
{% include templatename_details %}
{% else %}
<span class="text-warning">SHOULDNT APPEAR IF VUE WORKED </span>
{% endif %}
</div>
</bme-tab-pane>
{% endblock content %}
mydjangoappname/some_django_view.js:
import Vue from 'vue';
import Vuex from 'vuex';
//now Vue is using Vuex, which injects $store centralized state variables as needed
Vue.use(Vuex);
//KEY: re-using components defined once.
import {base_messages, base_components} from '../mysite/commonbase.js';
var local_components = {
//nothing, but I could have imported some other components to mix-n-match
//in any case, bme-nav-item, bme-tab-pane and bme-user-messages need to
//coming from somewhere for this page!
};
const components = Object.assign({}, base_components, local_components);
//we're going to put together a Vue on the fly...
export function dovue(config) {
//KEY: The store is a Vuex object - don't be fooled, it's not SPA-only
// it's the easiest way to coherently share data across Vue Components, so use it.
store.commit('initialize', config);
//here I am telling the store which html IDs need hiding
var li_tohide = settings.li_tohide || [];
li_tohide.forEach(function(hidden) {
store.commit('add_hidden', hidden);
});
/* eslint-disable no-new */
var vm = new Vue({
//KEY: This tells the Vue instance what parts of your html are in its scope.
el: '#bme-vue'
//KEY: each bme-xxx and bme-yyy special tag needs to be found in components below
//otherwise you'll see my SHOULDNT APPEAR IF VUE WORKED text in your page
,components: components
,data: {
li_rowcount: window.settings.li_rowcount || []
,csrf_token: window.csrf_token
,url_batch: "some url"
}
,mounted: function () {
// a Vue lifecycle hook. You could use to set up Vue Event listening for example
console.log("data.js.lifecycle.mounted");
}
,methods : {
,run_batch: function(e) {
//hook this up to a button
console.assert(this.$data, COMPONENTNAME + ".run_batch.this.$data missing. check object types");
var url = e.target.dataset.url
//this is defined elsewhere
post_url_message(this, url, this.csrf_token);
}
}
//the Vuex instance to use for this Vue.
,store: store
});
//did Django provide any user messages that need displaying?
var li_user_message = config.li_user_message || [];
li_user_message.forEach(function(user_message, i) {
//the bme-user-messages Component? It's listening for this event
//and will display Bootstrap Alerts for them.
vm.$emit(base_messages.EV_USER_MESSAGE, user_message);
});
return vm;
}
//various app and page specific settings...
import {app_config, LOCALNAV_LINK, TOPNAV_LINK_OTHERS} from "./constants";
var page_config = {
//used to show which navigation items are .active
localnav_link : LOCALNAV_LINK.data
, topnav_link: TOPNAV_LINK_OTHERS.system_edit_currentdb
};
//this is coming from Django's RequestContext.
var generated_config = window.settings;
//ok, now we are merging together a Django app level config, the page config and finally
//what the Django view has put into settings. This will be passed to the Vuex store
//individual Vue Components will then grab what they need from their $store attribute
//which will point to that Vuex instance.
var local_config = Object.assign({}, app_config, page_config, generated_config);
var vm = dovue(local_config);
vuex/generic.js:
And a naive, mostly read-only store implementation:
//you can add your page's extra state, but this is a shared baseline
//for the site
const state = {
active_tab: ""
,topnav_link: ""
,localnav_link: ""
,li_user_message: []
,s_visible_tabid: new Set()
,urls: {}
};
const mutations = {
//this is what your page-specific JS is putting into the state.
initialize(state, config){
//initialize the store to a given configuration
//KEY: attributes that did not exist on the state in the first place wont be reactive.
// console.log("store.initialize");
Object.assign(state, config);
},
//a sample mutation
set_active_tab(state, tabid){
//which bme-tab-nav is active?
if (! state.s_visible_tab.has(tabid)){
return;
}
state.active_tab = tabid;
},
};
export {state as generic_state, mutations};
and to give you an idea of the general file hierarchy:
.
./manage.py
./package.json //keep this under version control
./
├── mydjangoappname
│ ├── migrations
│ └── static
│ └── mydjangoappname
├── node_modules
├ //lots of JavaScript packages here, deposited/managed via npm && package.json
├── static
│ └── js
├── static_src
│ ├── assets
│ ├── bundles
│ │ // this is where django-webpack-loader's default config deposits generated bundles...
│ │ // probably belonged somewhere else than under static_src ...
│ │ ├── mydjangoappname
│ ├── components
│ │ ├── mydjangoappname
│ ├── css
│ ├── js
│ │ ├── mydjangoappname
│ │ └── mysite
│ └── vuex
│ ├── mydjangoappname
├── staticfiles
│ // for Production, collectstatic should grab django-webpack-loader's bundles, I think...
├── templates
│ ├── admin
│ │ └── pssystem
│ ├── mydjangoappname
│ └── mysite
└── mysite
├── config
├ // where you configure webpack and the entry points.
├ webpack.config.development.js
├── sql
│ └── sysdata
├── static
│ └── mysite
└── templatetags
OK, I did have to modify the site's base template to make sure that div#bme-vue is always available.
Probably a bit of refactoring needed between this and mysite/__full12_vue.html.
mysite/__full12.html:
<!-- lots of stuff left out -->
<body>
<!-- KEY: the #bme-vue wrapper/css selector tells Vue what's in scope.
it needs to span as much of the <body> as possible, but
also end right BEFORE the render_bundle tag. I set that css
selector in mydjangoappname/some_django_view.js and I'd want to
use the same selector everywhere throughout my app.
-->
<div id="bme-vue">
<!-- anything that ends up here
, including through multiple nested/overridden Django content blocks
, can be processed by Vue
, but only when have Vue-relevant markup
such as custom component tags or v-for directives.
-->
...more blocks...
{% block search %}
{% endblock search %}
<div id="main" role="main">
<div> <!-- class="container"> -->
{% block content %}
{% endblock %}
</div>
</div>
...more blocks...
</div> <!-- bme-vue -->
{%block extra_js_body_end%}
{%endblock extra_js_body_end%}
</body>
</html>
This is how I integrate Vue with a Django project:
The first approach is building separate Django and Vue apps. Django will be responsible for serving the API built using Django REST framework and Vue will consume these APIs using the Axios client or the browser's fetch API. You'll need to have two servers, both in development and production, one for Django(REST API) and the other for Vue (to serve static files).
The second approach is different the frontend and backend apps will be coupled. Basically you'll use Django to both serve the Vue frontend and to expose the REST API. So you'll need to integrate Vue and Webpack with Django, these are the steps that you can follow to do that
First generate your Django project then inside this project directory generate your Vue application using the Vue CLI
For Django project install django-webpack-loader with pip:
pip install django-webpack-loader
Next add the app to installed apps and configure it in settings.py by adding the following object
WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': '',
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
}
}
Then add a Django template that will be used to mount the Vue application and will be served by Django
{ % load render_bundle from webpack_loader % }
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Django + Vue</title>
</head>
<body>
<div id="root">
This is where Vue will be mounted
</div>
{ % render_bundle 'app' % }
</body>
</html>
Then add an URL in urls.py to serve this template
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
urlpatterns = [
url(r'^', TemplateView.as_view(template_name="main.html")),
]
If you start both the Django and Vue servers at this point you'll get a Django error saying the webpack-stats.json doesn't exist. So next you need to make your Vue application able to generate the stats file.
Go ahead and navigate inside your Vue app then install webpack-bundle-tracker
npm install webpack-bundle-tracker --save
Go to build/webpack.base.conf.js then add
let BundleTracker = require('webpack-bundle-tracker')
module.exports = {
// ...
plugins: [
new BundleTracker({filename: '../webpack-stats.json'}),
],
}
This add the BundleTracker plugin to Webpack and tell it to generate the webpack-stats.json file in the parent folder where Django files live.
Now if you re-run your Vue server the webpack-stats.json will be generated and Django will be able to consume it to find information about the Webpack bundles generated by Vue dev server.
You can find more information from this tutorial.
I have created an sample hybrid app using telerik app builder CLI. The project loads an initial home screen from a COMPONENTS folder in the project. Now i have Home folder with an index.js and view.html in it and the Home folder is inside Components. I added About folder with an index.js and view.html in it.
Both view.html have a div inside it. Now i need to know how to navigate from home to about. This has to happen from the JS. I tried
var app = new kendo.mobile.Application();
app.navigate("#AboutView");
"#AboutView" is the id of the div in view.html in About folder. This doesn't work. Could someone provide any help
with remote views ... you will need to provide the full path. and the reference is always from the root of the project. so in your case it will be
components/About/view.html
http://docs.telerik.com/kendo-ui/mobile/application#remote-views