I have a very simple site where I'm using the most basic Vue.
When I load the site, it renders divs which are not supposed to show, for a fraction of a second, before hiding them. It makes the site look very unprofessional.
Here is the site if you want to experience the glory of flashing divs: http://sqlforever.com/
Looking around on the web, I've tried to use v-show, v-if and even v-cloak. None of them work.
Here is an example where I'm using v-show, along with v-cloak:
<div class="row v-cloak" v-show="display_schema">
...
</div>
The definition of v-cloak:
[v-cloak] { display:none; }
Vue definition:
const app = new Vue({
el: '#app',
data: {
...
errorMsg: "",
warnMsg: "",
...
display_schema: false,
...
Else where I'm using v-if:
<div class="row">
<div id = "errorPanel" v-if="errorMsg != ''" class="alert alert-danger alert-dismissible fade show v-cloak" role="alert">
<strong>ERROR: </strong> {{errorMsg}}
<!--button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button-->
</div>
<div id = "warnPanel" v-if="warnMsg != ''" class="alert alert-warning alert-dismissible fade show v-cloak" role="alert">
<strong>WARNING: </strong> {{warnMsg}}
<!--button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button-->
</div>
</div>
Currently I'm also loading css and js directly off the web, I'll load them locally when this goes 'production' but simple experiments didn't seem to make a difference.
I'm not normally a web dev but I've done a site or two using knockoutjs and don't remember having this issue.
What am I doing wrong?
You're using v-cloak but incorrectly. From the docs:
This directive will remain on the element until the associated Vue instance finishes compilation. Combined with CSS rules such as [v-cloak] { display: none }, this directive can be used to hide un-compiled mustache bindings until the Vue instance is ready.
It's a directive, not a class name. Your CSS is correctly styling it as an attribute:
[v-cloak] { display:none; }
But you need to apply it in your template as a directive, not a class name. For example, this will remove the flash of content:
<div class="container" id="app" v-cloak>
Related
So I have a form with multiple input fields, whenever I type something into these fields, somehow it manipulates the DOM, and removes a certain class active from the form container. Please see this GIF to see it.
Steps to reproduce:
Click create your account
Type anything in any of the shown field
Observe the faulty behavior (which is the result of removing the active class)
Template code:
// active class is getting injected here
<div class="login-forms__container">
<section class="new-user__section">
<form>
<h1>{{ $t('login.create-form.title') }}</h1>
<p>{{ $t('login.create-form.subtitle') }}</p>
<b-field>
<b-input
v-model="registerForm.fullName"
:placeholder="$t('login.create-form.name')"
type="text"
icon-pack="fas"
icon="user"
maxlength="25"
/>
</b-field>
....
<div class="field">
<small>
<a target="_blank" #click.prevent="toggleCreateAccount">
{{ $t('login.create-form.registered') }}
</a>
</small>
</div>
</form>
</section>
</div>
JS code:
methods: {
toggleCreateAccount () {
document
.querySelector('.login-forms__container')
.classList
.toggle('active');
},
What I've tried:
Disable/Enable hot reloading
Tracing DOM event listeners (through breakpoints)
Changing the class name (suspected that "active" name is too common and might get removed by other libraries)
Using e.preventDefault() and click.prevent;
Or even removing the function responsible for adding the class and inject the class manually through inspect elements
Note:- removing v-model fixes the issue
You're modifying the DOM manually in a way that Vue can't trace. When it comes time to rerender, it sees the class you added, but since it doesn't match the VDOM in the template (you don't have "active" in your template), it thinks it must be removed (VDOM = source of truth).
You should conditionally include the active class in your template, Vue will automatically patch the DOM for you.
An abbreviated example:
template: `<div :class="{'.login-forms__container': true, active: createAccountActive }">`,
data() {
createAccountActive: false,
},
methods: {
toggleCreateAccount() {
this.createAccountActive = !this.createAccountActive;
}
},
I'm learning how to use vue.js
I've a shared hosting plan where I can only use html. I'm fetching the data I need using axios and a remote wordpress installation that will act as a backend only. What I need to know, is how I can change the DOM content of the index.html using vue if the user click on a link and I need to change the layout of the page because a different presentation for the contents is needed?
See the example:
<div id="vue-app">
link to layout 2
<div class="col-12">starting layout </div>
</div>
// after the user click the link (v-on:click) the layout change
<div id="vue-app">
link to layout 1
// layout change
<div class="col-6">new layout </div>
<div class="col-6">new layout </div>
</div>
Please read up on Conditional Rendering in Vue.js.
You can have a boolean variable in the data compartment of your script tag and change it on click.
And in the tags put v-if="your_bool_variable".
<div id="vue-app" v-if="layout_switch">
link to layout 2
<div class="col-12">starting layout </div>
</div>
// after the user click the link (v-on:click) the layout change
<div id="vue-app" v-else>
link to layout 1
// layout change
<div class="col-6">new layout </div>
<div class="col-6">new layout </div>
</div>
Negate the boolean variable at the #click event.
Data could look like the following:
<script>
export default {
name: "YourComponent",
data: () => {
return {
layout_switch: true
}
},
methods: {
changeLayout() {
this.layout_switch = !this.layout_switch;
}
}
}
</script>
I have a feeling the answer to this question is quite simple, but I cannot find an answer to it anywhere. I am build a very simple app with Vue.js (v2.6.11) that consists of just two pages, a home page and another page with a form. Now, on both of these pages, there are several parallax containers made with MaterializeCSS. If you're unfamiliar, a parallax container is basically just a div with an image as its background, and when the user scrolls, the background image moves at a different rate than the foreground of the site.
My problem is that when I navigate from the home page to the page with the form using a Vue.js link, <router-link :to="{name: "FormPage"}>Form Page</router-link>, the images in the parallax containers DO NOT load. However, if I refresh the page, the images load fine and everything is well. Similarly, If I replace the <router-link> with a simple Form Page the images load fine, everything works as it should.
So my question is this: why don't my parallax container images load on the page navigated to with <router-link></router-link>, but then when I navigate to that same page with a the images do load? In other words, what is <router-link></router-link> doing that prevents my parallax container images from loading??
Any and all feedback would be appreciated. Otherwise, I hope you have a marvelous day, and thank you for you time in reading and or answering my question :)
--Update--
CODE:
This is the component on the homepage that contains the link in question:
<template>
<div id="index-banner" class="parallax-container" style="height: 400px;">
<div class="section no-pad-bot">
<div class="container">
<br><br>
<h1 class="header center white-text">{{ translations.title }}</h1>
<div class="row center">
<h5 class="header col s12 white-text light">{{ translations.subtitle }}</h5>
</div>
<div class="row center">
<!-- <router-link :to="{name: 'Generator', force: true }" class="btn-large waves-effect waves-light teal lighten-1 center-align">{{ buttonText }}</router-link> -->
{{ translations.buttonText }}
</div>
</div>
</div>
<div class="parallax"><img :src="img" alt="Unsplashed background img 1"></div>
</div>
</template>
<script>
export default {
name: 'Banner1',
props: {
translations: String,
img: String
},
}
</script>
<style>
</style>
This is the 'view' that is navigated to, containing the parallax containers in question:
<template>
<div>
<PageTitle
:translations="$t('generatorPage.components.pageTitle')"
img="/imgs/parallax5.jpeg"
/>
<SigForm
:translations="$t('generatorPage.components.sigForm')"
/>
<Separator
img="/imgs/parallax5.jpeg"
/>
</div>
</template>
<script>
import PageTitle from '#/components/banner/parallax/PageTitle'
import Separator from '#/components/banner/parallax/Separator'
import SigForm from '#/components/generator/SigForm'
export default {
name: 'Generator',
components: {
PageTitle,
SigForm,
Separator,
}
}
</script>
<style>
</style>
Here is the 'PageTitle' component with a parallax container:
<template>
<div class="parallax-container form-parallax-container">
<h1 class="white-text center">{{ translations.title }}</h1>
<div class="parallax"><img :src="img"></div>
</div>
</template>
<script>
export default {
name: 'PageTitle',
props: {
translations: String,
img: String
}
}
</script>
<style>
</style>
And here is the 'Separator' with a parallax container:
<template>
<div class="parallax-container form-parallax-container">
<div class="parallax"><img :src="img"></div>
</div>
</template>
<script>
export default {
name: 'Separator',
props: {
img: String
}
}
</script>
<style>
</style>
---UPDATE: Complete repo & sandboxed app---
Someone mentioned it would be eaiser if I provided a sandboxed app or whatever to debug it, so I just made the github repo public and also uploaded it to codesandbox.io. You'll notice that on codesandbox.io, the parallax images aren't even loading at all...on the homepage, on the form page, or upon refresh!
Ok so this is not the answer, but I needed to post some code to illustrate.
I have to confess that I'm not fully au-fait with JS frameworks, but I do know materializecss very well. I've been trying to help another user with a React based problem where the sidenav stops working when the react router is used - until he refreshes the page, when it works fine again.
So here's my hunch:
Parallax is a component that needs initialising like so:
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.parallax');
var instances = M.Parallax.init(elems);
});
// Or with jQuery
$(document).ready(function(){
$('.parallax').parallax();
});
If you leave that initialisation code out, it won't work. And, taken from the docs for select fields dynamically added components need reinitialising.
You must initialize the select element as shown below. In addition,
you will need a separate call for any dynamically generated select
elements your page generates.
So my hunch is that when the page is re-rendered via a navigator, we get a new component added to the dom - but this is after the initialisation has already run. So that component is not initialised.
Could be wrong, hope I'm not for your sake more than mine. As I said, I don't know Vue or React very well at all, and my suggestions to run the init at each render didn't work for the React issue - but there are so many moving parts it's hard to rule out.
I am working with Laravel Scout and alogolia as the driver. Since I have vue on the front end, I tried the vue instant search package which works really well.
The issue that I am facing is that I need to customize it to the in app styles we are using.
Refinement Section
This is the particular component I am trying to customize. It tried over riding the classes like they show in Styling Section but that won't cut it for me since I need to add more tags and attributes in there.
<ais-refinement-list attribute-name="categories.title" inline-template>
<div class="column w-1/5">
Hello
</div>
</ais-refinement-list>
Now I know I can start to write an inline template like so but what I don't understand yet, is how to get the values for refinements so I can make the checkboxes and furthermore how to send them back to the component once they are selected. Any help is appreciated.
I dug through the package it self here and then found the template inside here. For some reason I could not see this in vendor code.
Got all the variables and method calls from in there
This is the custom version:
<ais-refinement-list attribute-name="categories.title" inline-template>
<div class="column w-1/5">
<h3>Categories</h3>
<hr class="my-3">
<div class='column w-full mb-4' v-for="facet in facetValues">
<div class="checkbox-control mb-4">
<input type="checkbox" :id="facet.name" :value="facet.name" v-model="facet.isRefined" #change="toggleRefinement(facet)"/>
<label :for="facet.name">{{ facet.name }} ({{ facet.count }})</label>
</div>
</div>
</div>
</ais-refinement-list>
I'm building a simple Vue.js page and my HTML snippet is as follows:
<div id="vueApp">
<a href="#" class="button is-outlined" #click="showNextDiv" >Show Div</a>
<div class="modal animated fadeIn" v-bind:class="{ is-active: isActive }">
...
</div>
</div>
I'm using the Bulma CSS Framework and the "is-active" modifier makes the div active (as the name suggests).
My problem is that whenever I load the page the <div id="vueApp"> does not show up neither does the button that makes isActive turn true.
This is my vue instance declaration:
new Vue({
el: '#vueApp',
data: {
isActive: false
},
methods: {
showNextDiv: function(){
this.isActive = true;
}
}
});
The dash character in your CSS binding makes the name an invalid javascript property name so you need to enclose it in quotes:
v-bind:class="{ 'is-active': isActive }"
I suspect there might be something in your console highlighting this error.
UPDATE
Should have included my jsFiddle showing that your JS and HTML code works if the is-active is wrapped in quotes:
https://jsfiddle.net/psteele/mzjb8wvb/