link1233 link1234 link1235 link1236 link1237 link1238 link1239 link1240 link1241 link1242 link1243 link1244 link1245 link1246 link1247 link1248 link1249 link1250 link1251 link1252 link1253 link1254 link1255 link1256 link1257 link1258 link1259 link1260 link1261 link1262 link1263 link1264 link1265 link1266 link1267 link1268 link1269 link1270 link1271 link1272 link1273 link1274 link1275 link1276 link1277 link1278 link1279 link1280 link1281 link1282 link1283 link1284 link1285 link1286 link1287 link1288 link1289 link1290 link1291 link1292 link1293 link1294 link1295 link1296 link1297 link1298 link1299 link1300 link1301 link1302 link1303 link1304 link1305 link1306 link1307 link1308 link1309 link1310 link1311 link1312 link1313 link1314 link1315 link1316 link1317 link1318 link1319 link1320 link1321 link1322 link1323 link1324 link1325 link1326 link1327 link1328 link1329 link1330 link1331 link1332 link1333 link1334 link1335 link1336 link1337 link1338 link1339 link1340 link1341 link1342 link1343 link1344 link1345 link1346 link1347 link1348 link1349 link1350 link1351 link1352 link1353 link1354 link1355 link1356 link1357 link1358 link1359 link1360 link1361 link1362 link1363 link1364 link1365 link1366 link1367 link1368 link1369

[Vue.js] Failed to execute 'readAsDataURL' on 'FileReader' the object is already busy reading Blobs Subscribe to RSS

to upload multiple images. When I choose multiple images photoSelected function is called. to use base64 but it shows this error on console.

PhotoSelected (e){
Let files = e.target.files;
Let reader = new FileReader();
Let file;
For (let i=0; I<files.length ; i++){
file = files [i];
reader.onload = (file) => {
This.product.photo[i] = reader.result;
}
reader.readAsDataURL(file)
}
}

Solution :

you defined the reader outside the for loop and use the same reader within the loop. this results in the reader being busy. You can solve this by creating one reader for each loop in its own scope, using an IIFE.

PhotoSelected (e){
let files = e.target.files;
let reader = new FileReader();
let file;
for (let i=0; I<files.length ; i++){
(function(file) {
var reader = new FileReader();
reader.onload = (file) => {
this.product.photo[i] = reader.result;
}
reader.readAsDataURL(file)
})(files[i]);
}
}

Since you are using let already and it uses block scope, you could also create a reader each loop using let.

PhotoSelected (e){
let files = e.target.files;

let file;
for (let i=0; I<files.length ; i++){
let reader = new FileReader();
file = files [i];
reader.onload = (file) => {
this.product.photo[i] = reader.result;
}
reader.readAsDataURL(file)
}
}

[Vue.js] Echarts.js Detect a click on a subset of data Subscribe to RSS

to detect a click on a particular subset in a bar chart. As to init a new chart after the click, with the data from the clicked subset. Currently when I click on chart bars, I get data of the whole chart and can’t retrieve data of just one bar.

Here is what I have:

<template>
<chart :options=”chartOptionsBar”
:autoresize=”true”
ref=”barChart”
@click=”mergeOptions(chartOptionsBar)”></chart>
<template>

<script>

export default {
data() {
return {
manualOptions: ‘’,
chartOptionsBar: {
xAxis: {
data: [‘Q1’, ‘Q2’, ‘Q3’, ‘Q4’],
},
yAxis: {
type: ‘value’,
},
series: [
{
type: ‘bar’,
data: [
{ value: 335, name: ‘1’ },
{ value: 310, name: ‘2’ },
{ value: 234, name: ‘3’ },
{ value: 135, name: ‘4’ },
],
},
],
title: {
text: ‘Quarterly Sales Results’,
x: ‘center’,
textStyle: {
fontSize: 24,
},
},
color: [‘#127ac2’],
},
};
},
methods: {
mergeOptions (options) {
console.log(options.series[0]);
},
},
};
</script>

Solution :

In the click handler you are passing in a reference to the original config object for the chart, so this is what will be available to you in the mergeOptions function

If you remove the parenthesis and argument the function will get the event information for the click event @click=”mergeOptions”

mergeOptions (eventInfo) {
console.log(eventInfo);
// hopefully this information will be a bit more use
}

According to the documentation echarts.baidu.com/tutorial.html#Events%20and%20actions%20in%20ECharts%0D this information object will allow you to determine which bar was clicked.

Solution 2:

I managed to detect the clicked subset by adding a refs attribute and the click event to the component and passing a function. Then I put this function in methods:

methods: {
getDataSubset() {
this.$refs.barChart.chart.on(‘click’, (params) => {
this.subset = params.data;
});
},
},

[Vue.js] Vue.js Why is my Single File Component not being rendered/displayed in my template Subscribe to RSS

when currently learning how to build a web app using Vue.js. there is used the vue-cli (version 3.8.2), to scaffold a HelloWorld application.

there is modified the generated HelloWorld.vue.js component as follows:

/path/to/vue-app/src/components/HelloWorld.vue

<template>
<div class=”hello”>
<b-tabs content-class=”mt-3”>
<b-tab title=”module1” active>
<Module1/>
</b-tab>
</b-tabs>
</div>
</template>

<script lang=”ts”>
import { Component, Prop, vue.js } from ‘vue-property-decorator’;
import Module1 from ‘./Module1.vue’;

@Component
export default class HelloWorld extends vue.js {
@Prop() private msg!: string;
}
</script>

<!– Add “scoped” attribute to limit CSS to this component only –>
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

/path/to/vue-app/src/components/Module1

<template>
<div class=”module1”>
Module1
</div>
</template>

<script>
import { Component, Prop, vue.js } from ‘vue-property-decorator’;

@Component
export default class Module1 extends vue.js {
}
</script>

<style>
</style>

/path/to/vue-app/src/router.ts

import vue.js from ‘vue’;
import Router from ‘vue-router’;
import Home from ‘./views/Home.vue’;

Vue.use(Router);

export default new Router({
mode: ‘history’,
base: process.env.BASE_URL,
routes: [
{
path: ‘/‘,
name: ‘home’,
component: Home,
},
{
path: ‘/about’,
name: ‘about’,
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: “about” */ ‘./views/About.vue’),
},
],
});

When I navigate to http://localhost:8080/ The contents of my module Module1 is not being displayed on the page.

Why is the component not being rendered (displayed), and how do I resolve this issue?

Solution :

You must register the Module1 component before use it (it’s weird you didn’t get any error).
In typescript you have to register components inside the @Component decorator, like this:

@Component({
components: {
Module1
}
})

[Vue.js] Vue Group data by day, then by time Subscribe to RSS

I’m trying to group a list of events first by tay, and then by time. I’m able to get one layer of this, but I’m stuck on the second.

In the end, it should look something like this:

Friday
8:00 - Event 1, Event 2, etc
9:00 - Event 1, Event 2, etc

Saturday
8:00 - Event 1, Event 2, etc
9:00 - Event 1, Event 2, etc

Here’s my code so far, which gives me the day-level groupings. I’m extremely new to this, so if there’s an obviously better approach, I’m happy to explore it.

Here’s a CodePen version. This does the day grouping, but not the time grouping.

I’ve tried several things. I understand that I probably need to do something similar to what I’m doing with the date, but I’m not sure how to create, loop through, and display arrays that don’t exist yet.

<div id=”vue”>
<div v-for=”events, day in groupedDays” class=”day”>
<h2>{ day == today ? ‘Today’ : day }</h2>
<div v-for=”event, time in events”>
{ event.date.toLocaleTimeString() } - { event.title }
</div>
</div>
</div>

function groupBy(array, fn) {
let result = {};
array.forEach(item => {
let key = fn(item);

if (!result[key]) {
result[key] = [];
}
result[key].push(item);
});
return result;
}

let conferenceDays = [];

for (let [key, session] of Object.entries(sessions)) {
// console.log(session.Start);
conferenceDays.push({
date: new Date(session.Start),
title: session.Title
});
}

new Vue({
el: “#vue”,
data() {
return {
conferenceDays,
today: new Date().toDateString()
};
},
computed: {
groupedDays() {
return groupBy(this.conferenceDays, day => day.date.toDateString());
}
}
});

I know somebody will very helpfully label this as a duplicate of some vaguely similar question, so please know that I did search extensively, and I didn’t locate any questions with two levels of groupings. Again, I’m open to different solutions if I’m approaching this in a bad way.

Solution :

A possible solution could be the following:

In the groupBy function, first sort the array in ascending order and then transform each day into an object whose keys and values would be the starting hours and the conferences that start at that time, respectively.

function groupBy(array) {
return array
.sort((c1, c2) => c1.date.getTime() - c2.date.getTime())
.reduce((acc, crt) => {
const k = crt.date.toDateString();
const hr = crt.date.toLocaleTimeString();

if (!acc[k]) {
acc[k] = {};
}

acc[k][hr] = acc[k][hr] || [];
acc[k][hr].push(crt.title);

return acc;
}, {})
}

As a result, the html would look like this:

<div v-for=”events, day in groupedDays” class=”day”>
<h2>{ day == today ? ‘Today’ : day }</h2>
<div v-for=”conferences, time in events”>
{ time } - { conferences.join(‘, ‘) }
</div>
</div>

Here’s the CodePen.

Solution 2:

for the data wrangling you propose you need to proceed in three steps:

i will use lodash as my data-plumbing library of choice, you dont have to use it

group all the conferences per day (that you have achieved)

function groupAllConferencesByDay(all) {
return _(all)
.groupBy(conference => conference.date.toDateString())
.mapValues(groupDaysConferencesByTime) // <—
.value()
}

for each day, group this days conferences by their timeslot

function groupDaysConferencesByTime(day) {
return _(day)
.groupBy(conference=>conference.date.toLocaleTimeString())
.mapValues(concatTitleOfSimultaniousConferences)
.value()
}

for each timeslot get the conferences titles and join them with commas

function concatTitleOfSimultaniousConferences(timeslot) {
return _.map(timeslot, conference => conference.title )
.join(“, “)
// dont need .value() here as we are using _.map(X, Y)
// as opposite to _(X).map(Y)
}

you can then present the data to user like

<div id=”vue”>
<div v-for=”events, day in groupedDays” class=”day”>
<h2>{ day == today ? ‘Today’ : day }</h2>
<div v-for=”conferences, time in events”>
{ time } - { conferences }
</div>
</div>
</div>

pen here

[Vue.js] Finding a way to create a HTTPS REST api connection through ip address (incl SSL cert) Subscribe to RSS

I need help with finding a method to create a SSL cert for my IP address so that I can use the REST api between my frontend vue.js and backend Express.

NGINX is the web server. And it serves the frontend and it redirects the connection to HTTPS with SSL cert from Let’s Encrypt. However there is a mixed protocol error when the frontend connects with the backend as it is served through HTTP.

My workaround was to create a HTTPS server for the Express files. But I needed a SSL cert to validate the HTTPS server for Express and there are no SSL cert that is free for the address used to serve the Express files, which is the IP address. Some suggested using self-signed but they are only useful for development and now when trying to use it for production.

Solution :

The ssl certs which work for nginx also work for express.

If you are running Express only, then you can drop nginx completely and use https on express with the let’s encrypt certs.

Otherwise if you have an exotic configuration, then you can configure nginx as an ssl reverse proxy using proxy redirect to change the protocol. https://chase-seibert.github.io/blog/2011/12/21/nginx-ssl-reverse-proxy-tutorial.html

[Vue.js] Cypress JS custom commands not working in VUE CLI Subscribe to RSS

I’m trying to set up a custom command to add some session storage items in a project and it doesn’t seem to be firing.

The command is as follows

Cypress.Commands.add(“login”, () => {
window.sessionStorage.setItem(“token”, “tokengoeshere”);
window.sessionStorage.setItem(“username”, “phoenix”);
cy.visit(“http://localhost:8080");
});

there is added the file into cypress.json

“supportFile”: “tests/e2e/support/index.js”,

and the index.js looks like

// Import commands.js using ES2015 syntax:
import “./commands”;

When the tests fire session storage is empty

Solution :

Where are you calling that custom command?

You usually create custom commands in cypress/support/commands.js file and that makes those commands available under cy.

So paste this to the cypress/support/commands.js

Cypress.Commands.add(“login”, () => {
window.sessionStorage.setItem(“token”, “tokengoeshere”);
window.sessionStorage.setItem(“username”, “phoenix”);
cy.visit(“http://localhost:8080");
});

and then call it with cy.login() from any test file. Those are usually in cypress/integration folder. For example in the case a file cypress/integration/myTestsWithCustomCommand.js:

describe(“My tests using custom commands”, () => {

it(“1st test using custom command”, () => {
cy.login();
// rest of the code test
});
});

[Vue.js] Using Vue is prop for dynamic components passed via config object Subscribe to RSS

there is a confirmation popup vue.js component with a config object like so:

{
title: null,
message: null,
onConfirm: null,
onDismiss: null,
modal_class: null,
icon: null,
confirmBtnText: null,
confirmBtnColor: null,
component: null
}

In the template to have a “dynamic” component rendered here:

<component class=”component-container” :is=”component”></component>

when initializing the component passed in like so:

import {CarrierSaferInfo} from ‘./path/to/single-file-component.vue’
let SaferInfo = Vue.extend(CarrierSaferInfo)
let SaferComp = new SaferInfo({
propsData: {
carrier,
dom_class: ‘text-white’,
}
})
openConfirmDialog({
//…other props
component: SaferComp
})

But I’m getting the error:

Failed to mount component: template or render function not defined.

Edit:
I’ve tried now to use the actual $options object of the component after it is extended like so:

<component class=”component-container” :is=”component.$options”></component>

In the component definition the prop carrier is required. Event though in the $options object it shows that the carrier prop inside propsData is an object, it is still saying:

Missing required prop: carrier

So, making progress but now the propsData is not populating in the render function for some reason.

Solution :

I think you’re looking for v-bind rather than is. You can include is within a v-bind if you want to keep it all as one object.

const CarrierSaferInfo = {
props: {
dom_class: String,

carrier: {
required: true,
type: String
}
},

template: ‘<div :class=”dom_class”>{ carrier }</div>’
}

new Vue({
el: ‘#app’,

data() {
return {
component: null
}
},

methods: {
onClick() {
this.component = {
is: CarrierSaferInfo,
carrier: ‘hello’,
dom_class: ‘text-white’
}
}
}
})
<script src=”https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id=”app”>
<button @click=”onClick”>Open</button>
<component v-if=”component” v-bind=”component” />
</div>

It is important to note that I’ve got rid of SaferInfo, SaferComp and any mention of Vue.extend or new. Where I’ve got this.component = … you’d probably need to use something like this instead:

openConfirmDialog({
// … other props …
component: {
is: CarrierSaferInfo,
carrier,
dom_class: ‘text-white’
}
})

It can be made to work with is. Not sure if there’s a more direct way of doing this but a wrapper component can provide a render function that sets the props. e.g.:

const CarrierSaferInfo = {
props: {
dom_class: String,

carrier: {
required: true,
type: String
}
},

template: ‘<div :class=”dom_class”>{ carrier }</div>’
}

new Vue({
el: ‘#app’,

data() {
return {
component: null
}
},

methods: {
onClick() {
this.component = {
render(h) {
return h(CarrierSaferInfo, {
props: {
carrier: ‘howdy’,
dom_class: ‘text-white’
}
})
}
}
}
}
})
<script src=”https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id=”app”>
<button @click=”onClick”>Open</button>
<component v-if=”component” :is=”component” />
</div>

Solution 2:

This looks rather relevant: https://top10webjs.com/2019/02/02/vue-js-passing-props-dynamically-to-dynamic-component-in-vuejs/

<component :is=currentComponent v-bind=currentProperties></component>

Via the syntax here :
https://vuejs.org/v2/guide/components-props.html#Passing-the-Properties-of-an-Object

[Vue.js] How to change user English number to Persian/Arabic instantly after user writes in the input tag? Subscribe to RSS

i’m using Vuejs and to prevent input tag from showing user’s characters and replace it with my own characters(which is some numbers).

there is already used @onchange and Watch and also getters and setters in computed. the problem is the character instantly appears on input and then changes to what i want.

<input v-model=”phonenumber” id=”downloadlink” v-
on:keydown=”sendDownloadLink” placeholder=””
maxlength=”11” autocomplete=”off”
\>

and in methods:

sendDownloadLink(e){
this.phonenumber = this.toPersianNum(this.phonenumber);
}

Thanks in Advance.

Solution :

There are a few problems here that are difficult to overcome:

Only the input event is a reliable. Keyboard events won’t necessarily fire if the value changes by copy/paste or drag/drop.
The input event fires after the input has been updated, so the characters the user types will be seen, albeit briefly, until the event listener can change them.
If the user changes characters in the middle of the value the position of the text cursor will jump to the end when updating the value to use the new numerals.

One way this could be approached is by using a font that shows the desired numerals for the characters 0 to 9. This would dodge most of the difficulties.

The code below attempts a JavaScript solution instead. It uses the input event as a catch-all. To try to prevent the wrong characters showing temporarily it cancels the keypress event and makes the necessary changes to the value itself. In all cases it tries to preserve the position of the text cursor using setSelectionRange.

This is not a particularly good demonstration of ‘correct’ vue.js usage but I’m not sure the functionality can be achieved without resorting to direct DOM manipulation.

new Vue({
el: ‘#app’,

data() {
return {
phoneNumber: ‘’
}
},

methods: {
getInputValue() {
const input = this.$refs.input
const value = input.value
const start = input.selectionStart
const end = input.selectionEnd

return [
value.slice(0, start), // before selection
value.slice(start, end), // selection
value.slice(end) // after selection
]
},

onInput() {
this.setInputValue(…this.getInputValue().map(this.toArabicNumerals))
},

onKeyPress(ev) {
ev.preventDefault()

const [before, , after] = this.getInputValue()
const keyValue = this.toArabicNumerals(ev.key)

this.setInputValue(before + keyValue, ‘’, after)
},

setInputValue(before, selection, after) {
const input = this.$refs.input
const start = before.length
const end = start + selection.length

this.phoneNumber = input.value = before + selection + after

input.setSelectionRange(start, end)
},

toArabicNumerals(str) {
return str.split(‘’).map(chr => {
if (‘0’ <= chr && chr <= ‘9’) {
return String.fromCharCode(+chr + 1632)
}

if (‘\u0660’ <= chr && chr <= ‘\u0669’) {
return chr
}

return ‘’
}).join(‘’)
}
}
})
<script src=”https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id=”app”>
<input
ref=”input”
:value=”phoneNumber”
@input=”onInput”
@keypress=”onKeyPress”
\>
</div>

You may find that you can remove the onKeyPress listener altogether. On the hardware I had available for testing it didn’t seem to make any difference but that might not be true for slower machines. The method setInputValue updates the <input> element’s value directly and it may be that that is sufficient to get the desired results without the need for onKeyPress.

[Vue.js] How can chips inside a disabled v-select be made clickable? Subscribe to RSS

there is a v-select that is representing the selected items with v-chips internally. the chips to be used as buttons when the user is not editing the selection, however the v-select is disabled when the user is not editing the selection. Since the v-select is disabled, none of the @click events I bind to the v-chip work, since the disable behavior cascades down to the v-chips. Since the v-select needs to be disabled to prevent the dropdown behavior, how can I enable my @click events on the v-chip elements.

See this CodePen for my rough setup: https://codepen.io/anon/pen/orLxMz

Solution :

It looks like the disable property of the v-select adds a

pointer-events: none;

style to all of its descendants. This is what is preventing the @click events from firing.

To re-enable the v-chips for clicking, add the style

pointer-events: all;

to the v-chip declaration.

See this working CodePen: https://codepen.io/anon/pen/QXEKLN