Vue.js showing content that should be hidden by a v-if tag when user refreshes page - vue.js

I have a Vue.js app that loads content in the created() method. I use a v-if tag to hide all of my UI until that content is loaded and ready to go. It works fine on the initial load, but if a user were to hit refresh in Chrome then the app displays (flashes momentarily) content that would not otherwise be displayed (based on the data being loaded in created).
From what I understand using the v-if tag, with a flag from my vuex store that indicates when the load has completed, is the proper way to hide content until I am ready to display it.
How can I avoid having the content flash on the refresh?

Vue.JS has solved this using the v-cloak directive. (see docs)
You add the v-cloak directive to your application's root element:
<div id="app" v-cloak>
...
</div>
Then add this CSS rule to your application's stylesheet:
[v-cloak] {
display: none;
}
Everything within the app div will then be hidden until Vue has initialized.

Related

Vue rendering only part of my App.vue after a login

I am working on a Vue.js application that I am almost done, one major bug left. The bug/issue is that when you go to /login and login to the site you get redirected via a router push (tried replace too) and when this happens I want to render the whole dashboard. Currently since in my App.vue file the router view is a different part it only renders the dashboard info part and not my header or sidebar.
Pretty much imagine a dashboard without a header or sidebar. That's what's rendering. I'd be okay if I could do something like F5 does because then it all would load correctly though taking up to 2 seconds longer on login which is okay by me.
My App.vue file template code
<template>
<div class="fade page-sidebar-fixed page-header-fixed show page-container" v-if="!pageOptions.pageEmpty" v-bind:class="{
'page-sidebar-minified': pageOptions.pageSidebarMinified,
'page-content-full-height': pageOptions.pageContentFullHeight,
'page-with-top-menu': pageOptions.pageWithTopMenu,
'page-sidebar-toggled': pageOptions.pageMobileSidebarToggled,
'has-scroll': pageOptions.pageBodyScrollTop
}">
<Header />
<Sidebar v-if="!pageOptions.pageWithoutSidebar" />
<div id="content" class="content" v-bind:class="{ 'content-full-width': pageOptions.pageContentFullWidth, 'content-inverse-mode': pageOptions.pageContentInverseMode }">
<router-view></router-view>
</div>
</div>
<div v-else>
<router-view></router-view>
</div>
</template>
Looks like I have resolved my issue, it comes from vue-router and how I am doing that if statement in my template code. So in that code I am checking a boolean value then choosing which view to render. So I had though on all of my auth pages I set the value correctly on exit. Turns out not...
This was in my Login.vue file, idea was to have on an exit of the route that it would change the boolean to false which would let me render it right. This was something I did initally but had forgotten about till about 20 minutes ago.
Upon checking this I found the value was not being changed for some reason. So as a work around in the created part of my Dashboard.vue file I set the value to false explicitly
Login.vue
beforeRouteLeave (to, from, next) {
PageOptions.pageEmpty = false;
next();
},
Dashboard.vue
created() {
PageOptions.pageEmpty = false;
...
}
The main idea is to have several base pages each one of them is operate with its own set of internal views.
You have to redirect user to another view, which is the one and only active view and this view can contains sidebar header and main part that also contains router-view, and then! you load any needed components in it.
You have to have something like that:
App component is only contains router view tag and any other pages are load into this.
The routes structure then looks like that:
As you can see, there are two base views load in App view. And then the base view can has a lot of children. The level of nested routes is up to you. Here is the contents of my app Home view:
And the MainContent component which is contains router view only:
The good example of project structure is the one generated with vue-cli. You can use it to simplify dev process with a lot of benefits and good practice solutions.

VueJS nexttick and IE11

Recently $nexttick appears to have broken on IE 11, in particular regarding input bound variable. This is causing forms with dynamic content to submit missing the required data
<form id="something" action="/" method="post">
<input type="hidden" name="token" :value="token" />
</form>
// js code
promise.then(function() {
self.$nextTick(function () {
document.getElementById('something').submit();
});
});
We have found that using the setTimeout for 1 second around the form submission allows enough time for the DOM to be updated so the token can be included in the form submission.
Has there been any changes to nexttick / IE11 that we need to account for?
nextTick allows you to do something after you have changed the data and VueJS has updated the DOM based on your data change, but before the browser has rendered those changed on the page. If you want to explicitly re-render the DOM, use requestAnimationFrame or setTimeout.
You could check this thread.

compile dynamic vue.js content added via ajax call

I am using vue.js 2.0 and have a problem.
I have a custom component which is loaded with the page, but the element that uses the component isn't used until a button is pressed, at that point the HTML is loaded and added to the DOM in a slide panel (whose content is dynamic).
Edit: It might be usuful to know the slide panel is dynamicly created using the jquery-slidepanel plugin... meaning I can't put a a placeholer in it like this:
<div id="slidePanel">
<component v-bind:is="test-thing">
<DYNAMIC CONTENT>
</component>
</div>
My problem is the instead on the component rendering the new content correctly I just see the {{ someitem }} all over the place.
here is a jsFiddle demonstrating what I am talking about: jsfiddle example

How to mix Vue components with HTML outside the template

Think about a wordpress blog, or a standard CMS with some content. I use a wysiwyg editor (CKEditor) to write my contents and save them to db.
I want to use some Vue components inside this HTML, and so I add a wrapper div to my theme. HTML pages are wrapped by
<div id="#my-custom-app">
...html from server
</div>
Basically I want to add for example
<my-app-image-compare></my-app-image-compare>
using CKEditor inside my HTML, then I will create an app mounted on #my-custom-app div. I will insert the app at the end of the html body.
Vue.app file doesn't have a template, the template is basically my HTML page written with CKEditor, but every component is loaded and defined by the app and every component has a template.
How can I do? Is there a way to have a main Vue app file without a defined template?
Option 1:
First create a vue container on a basic template. This template will then load a component which gets your data from the sever and displays it, so:
// This is your main vue instance container
<div id="#my-custom-app">
<dynamic-html v-if="myHtmlFromServer" template="myHtmlFromServer"></dynamic-html>
</div>
Within this main component, you need to hook up created event and populate myHtmlFromServer with your HTML content from the editor.
import DynamicHtml from './myComponents/DynamicHtml'
new Vue({
el: '#my-custom-app',
data () {
return {
myHtmlFromServer: ''
}
},
components: {
DynamicHtml
}
created () {
// this.myHtmlFromServer = this.getDataFromServer()
}
})
The <dynamic-html> component, would have props: ['template'] and on the created event would assign this.$options.template = this.template.
This option will set the HTML template of that component and allow Vue to render it as normal (meaning you can then do {{someVal}} in your CKEditor.
Option 2:
Another option is if you're using a server side language like PHP, then you could just put that html on the page i.e echo $myHtmlContent and as long as that content contains <div id="#my-custom-app"> you Vue instance will mount. PHP will add the HTML to the page before the JS processes the page so it'll just work.

dojo 1.8: loading dojo-laced html files into contentpane

Hi Any idea how I can load dojo-laced html file dynamically into contentpanes?
I am able to load non-dojo html into content pane using href.
When I loaded dojo-laced html file, I can see text in html tags but not text in dojo scripts. Where did I go wrong?
The scripts I put here are:-
widget.set('href','dojotext.html')
Another problem in jsfiddle is that pressing button 1 will not update, unlike in my environment.
and funny thing is that border container and comtent panes are not displayed, unlike in my environment too.
Here are my links in jsfiddle
- main page for testing loading
- dojo content to be loaded
Please advise. Thanks
Clement
First of all, your ContentPanes and BorderContainer are not being displayed because you're not parsing them.
In your code, you can run parser manually:
ready(function () {
parser.parse();
// ...
});
Regarding your first question, it seems that you didn't read the documentation:
<div id="foo" data-dojo-type="dijit/layout/ContentPane" href="/some/page.html">
<script type="dojo/method">
alert ('Hello World!');
</script>
</div>
Code from: ContentPane documentation