link2192 link2193 link2194 link2195 link2196 link2197 link2198 link2199 link2200 link2201 link2202 link2203 link2204 link2205 link2206 link2207 link2208 link2209 link2210 link2211 link2212 link2213 link2214 link2215 link2216 link2217 link2218 link2219 link2220 link2221 link2222 link2223 link2224 link2225 link2226 link2227 link2228 link2229 link2230 link2231 link2232 link2233 link2234 link2235 link2236 link2237 link2238 link2239 link2240 link2241 link2242 link2243 link2244 link2245 link2246 link2247 link2248 link2249 link2250 link2251 link2252 link2253 link2254 link2255 link2256 link2257 link2258 link2259 link2260 link2261 link2262 link2263 link2264 link2265 link2266 link2267 link2268 link2269 link2270 link2271 link2272 link2273 link2274 link2275 link2276 link2277 link2278 link2279 link2280 link2281 link2282 link2283 link2284 link2285 link2286 link2287 link2288 link2289 link2290 link2291 link2292 link2293 link2294 link2295 link2296 link2297 link2298 link2299 link2300 link2301 link2302 link2303 link2304 link2305 link2306 link2307 link2308 link2309 link2310 link2311 link2312 link2313 link2314 link2315 link2316 link2317 link2318 link2319 link2320 link2321 link2322 link2323 link2324 link2325 link2326 link2327 link2328

[Vue.js] Vue.js asyncronous components, named import

I know how to load asynchronous component in Vue. This

import MyComponent from ‘@/components/MyComponent’

export default {
components: {
MyComponent
}
}

is replaced like

export default {
components: {
MyComponent: () => import(‘@/components/MyComponent’)
}
}

But how can I replace “named” component import, like this?

import { SweetModal } from ‘sweet-modal-vue’

export default {
components: {
SweetModal
}
}

How do I import that asynchronously?

Solution :

You could use at the same way, but getting the specific component:

export default {
components: {
SweetModal: () => import(‘sweet-modal-vue’).then(m => m.SweetModal)
}
}

I recommend you to read this: Async Vue.js Component

[Vue.js] Authentication using Jwt and nodejs

when having two issues.

1.when when trying to perform authentication using JWT token and Nodejs when able to log in and log out but when I logged in if I refresh the page the navbar disappears.

when when not logged in in the login page I gave a link to the registration page when I click that it is not redirecting to that page. This is happening when I don’t give the nav bar to authenticate.

This is Login page

<template>
<div class=”container”>
<div class=”row”>
<div class=”col-md-6 mt-5 mx-auto”>
<form v-on:submit.prevent=”login”>
<h1 class=”h3 mb-3 font-weight-normal”>Please sign in</h1>
<div class=”form-group”>
<label for=”email”>Email Address</label>
<input type=”email” v-model=”email” class=”form-control” name=”email” placeholder=”Enter Email” required>
</div>
<div class=”form-group”>
<label for=”password”>Password</label>
<input type=”password” v-model=”password” class=”form-control” name=”email” placeholder=”Enter Password” required>
</div>
<button class=”btn btn-lg btn-danger btn-block” type=”submit”>Login</button>
<a href=”/register”>New User? Register here</a>
</form>
</div>
</div>
</div>
</template>

<script>
import axios from ‘axios’
import router from ‘../router’
import EventBus from ‘./EventBus’
import Navbar from ‘@/components/Navbar’
export default {
components: {Navbar},
data () {
return {
email: ‘’,
password: ‘’
}
},

methods: {
login () {
axios.post(‘http://localhost:5000/users/login',
{
email: this.email,
password: this.password
}).then((res) => {
localStorage.setItem(‘usertoken’, res.data)
this.email = ‘’
this.password = ‘’
if (res) {
this.emitMethod()
router.push({ name: ‘profile’ })
}
}).catch(err => {
console.log(err, alert(‘User doesnot exist’))

})
},
emitMethod () {
EventBus.$emit(‘logged-in’, ‘loggedin’)
}
}
}
</script>

This is the script when using for logout

logout () {
localStorage.removeItem(‘usertoken’)
}

User routes

const express = require(“express”)
const users = express.Router()
const cors = require(“cors”)
const jwt = require(“jsonwebtoken”)
const bcrypt = require(“bcryptjs”)

const User = require(“../model/User”)
users.use(cors())

process.env.SECRET_KEY = ‘secret’

users.post(“/register”, (req, res) => {
const today = new Date()
const userData = {
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password,
city: req.body.city,
cycle: req.body.cycle,
created: today
}

User.findOne({
where: {
email: req.body.email
}
})
.then(user => {
if (!user) {
bcrypt.hash(req.body.password, 10, (err, hash) => {
userData.password = hash
User.create(userData)
.then(user => {
res.json({ status: user.email + ‘ registered’ })
})
.catch(err => {
res.send(‘error: ‘ + err)
})
})
} else {
res.json({ “error”: ‘User already exists’ })

}
})
.catch(err => {
res.send(‘error: ‘ + err)
})
})

users.post(“/login”, (req, res) => {
User.findOne({
where: {
email: req.body.email
}
})
.then(user => {
if (user) {
if (bcrypt.compareSync(req.body.password, user.password)) {
let token = jwt.sign(user.dataValues, process.env.SECRET_KEY, {
expiresIn: 1440
})
res.send(token)
}
} else {
res.status(400).json({ error: ‘User does not exist’ })
}
})
.catch(err => {
res.status(400).json({ error: err })

})
})

users.get(‘/profile’, (req, res) => {
var decoded = jwt.verify(req.headers[‘authorization’], process.env.SECRET_KEY)

User.findOne({
where: {
userId: decoded.userId
}
})
.then(user => {
if (user) {
res.json(user)
} else {
res.send(‘User does not exist’)
}
})
.catch(err => {
res.send(‘error: ‘ + err)
})
})

users.put(“/:userId”, (req, res) => {
if (!req.body.firstName,
!req.body.lastName,
!req.body.city,
!req.body.cycle,
!req.body.biography) {
res.status(400)
res.json({
error: “Bad Data”
})
} else {
User.update(
{ firstName: req.body.firstName,
lastName: req.body.lastName,
city: req.body.city,
cycle: req.body.cycle,
biography: req.body.biography
},
{ where: { userId: req.params.userId } }
)
.then(() => {
res.send(“Contact updated”)
})
.error(err => res.send(err))
}
})

module.exports = users

Solution :

when not sure if the web app you are building is just for fun or you are planning to use it in production, if so I will suggest you not to use localStorage to save the token. A JWT needs to be stored in a safe place inside the user’s browser.

If you store it inside localStorage, it’s accessible by any script inside the page (which is as bad as it sounds as an XSS attack can let an external attacker get access to the token).

Don’t store it in local storage (or session storage). If any of the 3rd part scripts you include in the page gets compromised, it can access all the users’ tokens.

The JWT needs to be stored inside an HttpOnly cookie, a special kind of cookie that’s only sent in HTTP requests to the server, and it’s never accessible (both for reading or writing) from JavaScript running in the browser.

Source:

https://auth0.com/docs/security/store-tokens
https://logrocket.com/blog/jwt-authentication-best-practices/
https://blog.usejournal.com/sessionless-authentication-withe-jwts-with-node-express-passport-js-69b059e4b22c

Now going back to the original question, I see

import Navbar from ‘@/components/Navbar’

But I don’t you use it in the template, also can you post the vue.js component in which you are having issues with?

[Vue.js] Can you pass an element to a function within the template in Vue?

I’m trying to calculate and set an element’s max-height style programmatically based on the number of children it has. there is to do this on four separate elements, each with a different number of children, so I can’t just create a single computed property. I already have the logic to calculate the max-height in the function, but I’m unable to pass an element from the template into a function.

I’ve tried the following solutions with no luck:

<div ref=”div1” :style=”{ maxHeight: getMaxHeight($refs.div1) }”></div>
This didn’t work because $refs is not yet defined at the time I’m passing it into the function.
Trying to pass this or $event.target to getMaxHeight(). This didn’t work either because this doesn’t refer to the current element, and there was no event since I’m not in a v-on event handler.

The only other solution I can think of is creating four computed properties that each call getMaxHeight() with the $ref, but if I can handle it from a single function called with different params, it would be easier to maintain. If possible, I would like to pass the element itself from the template. Does anyone know of a way to do this, or a more elegant approach to solving this problem?

Solution :

Making a custom directive thata operates directly on the div element would probably be the best shot. You could create a directive component like:

export default {
name: ‘maxheight’,
bind(el) {
const numberOfChildren = el.children.length;

// rest of the max height logic here

el.style.maxHeight = ‘100px’;
}
}

Then just make sure to import the directive in the file you plan on using it, and add it to the div element:

<div ref=”div1” maxheight></div>

Solution 2:

A cheap trick I learned with vue.js is that if you require anything in the template that isnt loaded when the template is mounted is to just put a template with a v-if on it:

<template v-if=”$refs”>
<div ref=”div1” :style=”{ maxHeight: getMaxHeight($refs.div1) }”></div>
</template>

around it. This might look dirty at first, but the thing is, it does the job without loads of extra code and time spend and prevents the errors.

Also, a small improvement in code length on the expandable-function:

const expandable = el => el.style.maxHeight =
( el.classList.contains(‘expanded’) ?
el.children.map(c=>c.scrollHeight).reduce((h1,h2)=>h1+h2)
: 0 ) + ‘px’;

Solution 3:

I ended up creating a directive like was suggested. It tries to expand/compress when:

It’s clicked
Its classes change
The element or its children update

vue.js component:

<button @click=”toggleAccordion($event.currentTarget.nextElementSibling)”></button>
<div @click=”toggleAccordion($event.currentTarget)” v-accordion-toggle>
<myComponent v-for=”data in dataList” :data=”data”></myComponent>
</div>

…..

private toggleAccordion(elem: HTMLElement): void {
elem.classList.toggle(“expanded”);
}

Directive: Accordion.ts

const expandable = (el: HTMLElement) => el.style.maxHeight = (el.classList.contains(“expanded”) ?
[…el.children].map(c => c.scrollHeight).reduce((h1, h2) => h1 + h2) : “0”) + “px”;

Vue.directive(“accordion-toggle”, {
bind: (el: HTMLElement, binding: any, vnode: any) => {
el.onclick = ($event: any) => {
expandable($event.currentTarget) ; // When the element is clicked
};

// If the classes on the elem change, like another button adding .expanded class
const observer = new MutationObserver(() => expandable(el));
observer.observe(el, {
attributes: true,
attributeFilter: [“class”],
});
},
componentUpdated: (el: HTMLElement) => {
expandable(el); // When the component (or its children) update
}
});

[Vue.js] Bind color with Vuejs

to give icon color with for loop. there is tried in this way. But getting no result. I know it’s possible to bind style.

<v-tab v-for=”navtab in navtabs” :key=”navtab”>
<v-icon color=”{ navtab.color }”>{ navtab.icon }</v-icon>
</v-tab>

Data property:

<script>
export default {
data () {
return {
navtabs: [
{
icon: ‘info’,
name: ‘About Book’,
color: ‘teal darken-2’
},

{
icon: ‘favorite’,
name: ‘Specification’,
color: ‘orange darken-2’
}
]
}
}

How can I do this?

Solution :

You should not use:

<v-icon color=”{ navtab.color }”>{ navtab.icon }</v-icon>

Instead, bind the variable color:

<v-icon :color=”navtab.color”>{ navtab.icon }</v-icon>

[Vue.js] Vue not applying style class

there is single-file components that are built with the following Webpack configuration:

const { VueLoaderPlugin } = require(‘vue-loader’);

module.exports = {
module: {
rules: [
{
test: /\.vue$/,
use: ‘vue-loader’
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: ‘url-loader’,
options: {
limit: 8192
}
}
]
},
{
test: /\.css$/,
use: [
‘vue-style-loader’,
{
loader: ‘css-loader’,
options: {
modules: true,
localIdentName: ‘[local]_[hash:base64:8]‘
}
}
]
}
]
},
plugins: [
new VueLoaderPlugin()
]

I use the <style scoped> tag to style my components. This works with tag selectors (e.g. nav), but class selectors (e.g. .content) result in no styling. The DOM contains the relevant classes, but the generated dist/main.js file only contains a content_xgKyi9qt[data-v-ab83c772] selector, which is not applied, as the component only has the raw content class.

Solution :

Turns out the vue-style-loader options that I used are causing the name mangling. there is decided to switch from <style scoped> to <style module> and use the <div :class=”$style.content”> syntax instead.

This causes the class of the element to correspond to the mangled name and provides a level of isolation for styling.

[Vue.js] show / hide the element by using v-show attributes in Vue js

Here my myVueInstance having two radio button and one text box. Based on click radio button options I should show / hide the text box.

<div id=’myVueInstance’>

<label>Show Text box or not ? </label>
<input type=”radio” id=”one” value=”true” v-model=”picked”>
<label for=”one”>Yes</label>

<input type=”radio” id=”two” value=”false” v-model=”picked” >
<label for=”two”>No</label>
<br>
<span>Picked: { picked }</span>
<input type=’text’ v-show=’picked’>

</div>

<script type=”text/javascript”>
var app = new Vue({
el:’#myVueInstance’,
data:{

title : ‘My learning of Vue’,
picked:true
}
});
</script>

Note : I’m using vue.js updated version.

Solution :

Here, type of picked is becoming String when selecting radio button. Try this:

<input type=’text’ v-show=”picked === ‘true’”>



data:{

title : ‘My learning of Vue’,
picked: ‘true’
}

[Vue.js] how to call ajax request one time to load data in multiple component instances

In my vue.js project, there is a component which will load data via ajax request. The view page will use this component 3 times, and the request parameters and result are totally same. the ajax request be called only 1 time. what’s the best practice? I understand use the vuex store or session storage to save the ajax result in the component can do it, but is there any better idea?

jsfiddle link: jsfiddle.net/cqli/5g7anu0f/37

Template:

<div id=”app”>
<show-title></show-title>
<show-title></show-title>
<show-title></show-title>
</div>

Component definition:

Vue.component(‘show-title’, {
mounted(){
fetch(‘https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => this.title = json.title);
},
data: function () {
return {
title: “hello world!”
}
},
template:”<h3>{title}</h3>”
});
new Vue({
el: “#app”,
data: {
},
methods: {
}
})

Solution :

They’ll be the same, because you calling URL with same data: id = 1. You need to use props for the component:

Vue.component(‘show-title’, {
props: [‘id’], // here you defined props
mounted(){
fetch(‘https://jsonplaceholder.typicode.com/todos/'+this.id) // here you fetch todo with ID from props.
.then(response => response.json())
.then(json => this.title = json.title);
},
data: function () {
return {
title: “hello world!”
}
},
template:”<h3>{title}</h3>”
});

In the template add :id:

<show-title :id=”1”></show-title>
<show-title :id=”2”></show-title>
<show-title :id=”3”></show-title>

[Vue.js] Pass array to Laravel view in Vue

in laravel there is ProdoctController and CategoryController,
im passing the category data with this function:

public function view(){
$category = Category::all();
return view(‘admin.product.main’,[‘category’=>$category]);
}

its working with normal mode in laravel:

<select>
@foreach(category as categories)
<option value=’{category->id}”>{category->name}</option>
@endforeach
</select>

but in vue.js js there is a categories:[] in data,
and to use this:

<select v-model=”ProductCategory”>
<option v-for=”category in categories” :value=”categories.id”>categories.name</option>
</select>

how can i pass the data in categories array?

Solution :

You can do something like this:

<script type=”text/javascript”>
window.data = {!! json_encode([
‘categories’ => $categories,
]) !!};
</script>

<select v-model=”ProductCategory”>
<option v-for=”category in window.data.categories” :value=”category.id”>category.name</option>
</select>

First part gets you the categories onto the view in the JavaScript and then vue.js will have access to them. I think you should fix the category/categories variables, if this is a real code you’ve been using them not correctly, e.g. when you have a collection of many and when you have only one.

[Vue.js] Vuetify styles tags are not appeared in my web page

when working with Vuetify and try to make a web page but the vuetify components stylings are not appeared. Could you guide me. Thank you.

My code below.

<template>
<v-app>
<v-navigation-drawer v-model=”sidebar” app>
<v-list>
<v-list-tile v-for=”item in menuItems” :key=”item.title” :to=”item.path” @click>
<v-list-tile-action>
<v-icon>{ item.icon }</v-icon>
</v-list-tile-action>
<v-list-tile-content>{ item.title }</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-toolbar color=”indigo” dark fixed app>
<v-toolbar-side-icon @click.stop=”drawer = !drawer”></v-toolbar-side-icon>
<v-toolbar-title>
<router-link to=”/“ tag=”span” style=”cursor: pointer”>{ appTitle }</router-link>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items class=”hidden-xs-only”>
<v-btn flat v-for=”item in menuItems” :key=”item.title” :to=”item.path”>
<v-icon left dark>{ item.icon }</v-icon>
{ item.title }
</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-content>
<router-view/>
</v-content>
</v-app>
</template>
<script>
import vue.js from ‘vue’;
import Vuetify from ‘vuetify’;
import router from ‘@/router’;
Vue.use(Vuetify);

export default {
data() {
return {
appTitle: ‘MyEvents’,
sidebar: false,
drawer: null,
menuItems: [
{ title: ‘Home’, path: ‘/home’, icon: ‘home’ },
{ title: ‘Sign Up’, path: ‘/signup’, icon: ‘home’ },
{ title: ‘Sign In’, path: ‘/signin’, icon: ‘home’ }
]
};
}
};
</script>
<style>

expected page display like below.

But the as per code page display appear below.

Here my side navigation does not appear properly.

Solution :

Are you using vue-cli for the project?
If that, you have to install the plugin vue-cli-plugin-vuetify via vue.js ui.

Here the link: https://vuetifyjs.com/en/getting-started/quick-start

Greetings!

[Vue.js] Vue.js selected value in input does not match selected parameter

vue.js.js select after page load value what matches v-model but ignores :selected attribute.
Code:

<select class=”form-control “ :required=”true”
:class=”{‘is-invalid’: errors.has(‘item_‘+index) }”
:name=”‘item_‘+index”
v-validate=”‘required’”
v-model=”item.text_value”
v-if=”item.type ==’TYPE_TEXT’ “>
<option
v-for=”(itemz, index) in (getwords(item.product_parameter_value.text))”
:value=”itemz”
v-bind:selected=”index === 0”
\>{ itemz }</option>
</select>

The item.text_value is single word (Option2 etc)
getwords(item.product_parameter_value.text) returns array - [‘Option1’],[‘Option2’],[‘Option3’] etc.
So selected value always match item.text_value but not :selected.
Is there any way to set selected value to first item in array?

Solution :

You should control this by setting the v-model to the correct value, instead of by trying to force the DOM to be out of synch with the data model.

Ideally this would be done by just setting item.text_value in the data block of the component; if the correct value can’t be known ahead of time, you can read the getwords function before the component mounts to find the first element:

new Vue({
el: ‘#app’,
data: {
item: {
text_value: “” // ideally you would init the correct value here
}
},
methods: {
getwords() { // simplified stub for the data source:
return [“Option1”, “Option2”, “Option3”]
}
},

beforeMount() {
// if you can’t init it in the data block,
// read the value from getwords() here instead:
this.item.text_value = this.getwords()[0]
}
});
<script src=”https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id=”app”>
<select v-model=”item.text_value”>
<option v-for=”itemz, index) in (getwords())” :value=”itemz”>{itemz}</option>
</select>
</div>