link548 link549 link550 link551 link552 link553 link554 link555 link556 link557 link558 link559 link560 link561 link562 link563 link564 link565 link566 link567 link568 link569 link570 link571 link572 link573 link574 link575 link576 link577 link578 link579 link580 link581 link582 link583 link584 link585 link586 link587 link588 link589 link590 link591 link592 link593 link594 link595 link596 link597 link598 link599 link600 link601 link602 link603 link604 link605 link606 link607 link608 link609 link610 link611 link612 link613 link614 link615 link616 link617 link618 link619 link620 link621 link622 link623 link624 link625 link626 link627 link628 link629 link630 link631 link632 link633 link634 link635 link636 link637 link638 link639 link640 link641 link642 link643 link644 link645 link646 link647 link648 link649 link650 link651 link652 link653 link654 link655 link656 link657 link658 link659 link660 link661 link662 link663 link664 link665 link666 link667 link668 link669 link670 link671 link672 link673 link674 link675 link676 link677 link678 link679 link680 link681 link682 link683 link684

[Vue.js] How to toggle nested checkboxes (options) on check parent checkbox in Vue Js

there is simple questions list. It has some options and those options has some nested suboptions.
So need to keep hidden all nested checkboxes until checks parent checkbox.

i tried to do it but could not get it work.

there is tried this so far:

For better understanding please have a look at this fiddle

<div id=”app”>
<h2>Questions:</h2>
<ul>
<li v-for=”question in questions”>
<div class=”question”>{ question.question }</div>
<div class=”label__wrap” v-for=”option in question.options”>
<label>
<input type=”checkbox” v-model=”question.answer” :value=”option.option”>

<span>
{ option.option }
</span>
</label>

<div class=”sub__label__wrap” v-for=”opt in option.subOptions”>
<label>
<input type=”checkbox” v-model=”option.subOptsAnswers” :value=” opt.option”>

<span>
{ opt.option }
</span>
</label>
</div>

</div>
<br><br>
</li>
</ul>
</div>

Thanks.

Solution :

Updated Fiddle : https://jsfiddle.net/rcam67b9/

check the answers array whether the selected answer exist

v-if=”question.answer.indexOf(option.option) !== -1”

Final Code

<div id=”app”>
<h2>Questions:</h2>
<ul>
<li v-for=”question in questions”>
<div class=”question”>{ question.question }</div>
<div class=”label__wrap” v-for=”option in question.options”>
<label>
<input type=”checkbox” v-model=”question.answer” :value=”option.option”>

<span>
{ option.option }
</span>
</label>

<div class=”sub__label__wrap” v-for=”opt in option.subOptions” v-if=”question.answer.indexOf(option.option) !== -1”>
<label>
<input type=”checkbox” v-model=”option.subOptsAnswers” :value=” opt.option”>

<span>
{ opt.option }
</span>
</label>
</div>

</div>
<br><br>
</li>
</ul>
</div>

[Vue.js] How can I test data returned from an ajax call in mounted is correctly rendered?

there is a component (simplified)

<template>
<div v-if=”account”>
<h1 v-text=”accountName”></h1>
</div>
</template>
<script>
import repo from ‘../../repo’;

export default {
data() {
return {
account: {}
}
},
mounted() {
return this.load();
},
computed: {
accountName: function () {
return this.account.forename + ‘ ‘ + this.account.surname;
}
},
methods: {
load() {
return repo
.get(repo.accounts, {
params: {
id: this.$route.params.id
}
})
.then((response) => {
console.log(response.data);
this.account = response.data;
this.validateObj = this.account;
}, (error) => {

switch (error.response.status) {
case 403:
this.$router.push({name: ‘403’});
break;
default:
this.$refs[‘generic_modal’].open(error.message);
}

});
}
}
}
</script>

Which on mount, calls an API, gets the returned data, and renders the forename and surname.

I’m trying to write a mocha test to check that this works. I can do it using a timeout.

it(‘mounts’, done => {

const $route = {
params: {
id: 1
}
};

mock.onGet(‘/api/accounts/1’).reply(200, {
forename: ‘Tom’,
surname: ‘Hart’
});

const wrapper = shallowMount(AccountsEdit, {
i18n,
mocks: {
$route
}
});

setTimeout(a => {
expect(wrapper.html()).toContain(‘Tom Hart’);
done();
}, 1900);
});

But I wondered is there a better way? I was hoping to hook into the axios.get call, and run the check once that’s finished, however, I can’t seem to figure out how to do it.

EDIT: I tried using $nextTick, however, that didn’t work either

wrapper.vm.$nextTick(() => {
expect(wrapper.html()).toContain(‘Tom Hart’);
done();
});

{ Error: expect(received).toContain(expected) // indexOf

Expected substring: “Tom Hart”
Received string: “<div><h1>undefined undefined</h1></div>”
at VueComponent.<anonymous> (/home/tom/Dev/V6/Admin/.tmp/mocha-webpack/1554202885644/tests/Javascript/Components/Pages/account-edit.spec.js:37:1)
at Array.<anonymous> (/home/tom/Dev/V6/Admin/node_modules/vue/dist/vue.runtime.common.dev.js:1976:12)
at flushCallbacks (/home/tom/Dev/V6/Admin/node_modules/vue/dist/vue.runtime.common.dev.js:1902:14)
matcherResult: { message: [Function: message], pass: false } }
{ forename: ‘Tom’, surname: ‘Hart’ }
1) mounts

0 passing (2s)
1 failing

1) Accounts Edit Page
mounts:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure “done()” is called; if returning a Promise, ensure it resolves. (/home/tom/Dev/V6/Admin/.tmp/mocha-webpack/1554202885644/bundle.js)

EDIT 2: It seems just as a test, chaining $nextTick eventually works, so I guess something else is causing ticks before my call returns? Is there anyway to tell what caused a tick to happen?

wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
wrapper.vm.$nextTick(() => {
expect(wrapper.find(‘h1’).html()).toContain(‘Tom Hart’);
done();
});
});
});
});
});
});

Solution :

Hey we had similar problem and found this library:
https://www.npmjs.com/package/flush-promises

Which allow to us wait all promises before continue testing.
Try to do something like this:

const flushPromises = require(‘flush-promises’);

it(‘mounts’, (done) => {
const $route = {
params: {
id: 1
}
};

mock.onGet(‘/api/accounts/1’).reply(200, {
forename: ‘Tom’,
surname: ‘Hart’
});

const wrapper = shallowMount(AccountsEdit, {
i18n,
mocks: {
$route
}
});

flushPromises().then(() => {
expect(wrapper.html()).toContain(‘Tom Hart’);
done();
});
});

[Vue.js] Why do these queries work independently but not together?

there is 2 queries which to use on my firestore collection.

These 2 examples work:

database
.collection(‘servicebonnen’)
.where(‘medewerker’, ‘==’, ‘CEES’)

and:

database
.collection(‘servicebonnen’)
.where(‘date’, ‘>’, this.today)
.where(‘date’, ‘<’, this.tomorrow)

Why doesn’t combining these like so work?:

database
.collection(‘servicebonnen’)
.where(‘medewerker’, ‘==’, ‘CEES’)
.where(‘date’, ‘>’, this.today)
.where(‘date’, ‘<’, this.tomorrow)

Solution :

As mentioned in the firestore doc here:

You can also chain multiple where() methods to create more specific queries (logical AND). However, to combine the equality operator (==) with a range or array-contains clause (<, <=, >, >=, or array_contains), make sure to create a composite index.

So you need to create composite index in the case.

Solution 2:

As @hkchakladar mentioned I needed to add a composite index to generate results for non default queries.

[Vue.js] How to make temporary variable in VueJs' templates?

Is there a way to declare temporary variable in a VueJS template? My problem is that in a v-for i check if the actual value exists in an Array and if not I print another text, but for each element of the v-for it will do this twice (firstly to check if exists, and then to print the value) where with a variable it could be done once.

I’m using VueJS2 without any preprocessor nor template engines.

Here it’s my array :

let formats = [
{id: 1, label: “A3”},
{id: 1, label: “A4”},
{id: 1, label: “A5”},
{id: 1, label: “A6”},
];

Here is my template :

<tr v-for=”data in ajaxDatas”>
<td>
<template
v-if=”formats.find(e => {
return (e.shortEdge == data.height && e.longEdge == data.width) || (e.shortEdge == data.width && e.longEdge == data.height);
})”
\>
{ formats.find(e => {
return (e.shortEdge == data.height && e.longEdge == data.width) || (e.shortEdge == data.width && e.longEdge == data.height);
}).label }
</template>
<template v-else>
Other format
</template>
</td>
</tr>

As you can see it’s not really optimized… I was thinking in a way to make a temporary variable to stock the find return, something like this :

<tr v-for=”data in ajaxDatas”>
<td>
{
var f = formats.find(e => {
return (e.shortEdge == data.height && e.longEdge == data.width) || (e.shortEdge == data.width && e.longEdge == data.height);
});
f ? f.label : ‘Other format’
}
</td>
</tr>

FOR THE MOMENT i found a way but it’s not working properly, i can make something like this :

<tr v-for=”data in ajaxDatas”>
<td>
{ f = formats.find(e => {
return (e.shortEdge == data.height && e.longEdge == data.width) || (e.shortEdge == data.width && e.longEdge == data.height);
}) }
{ f ? f.label : ‘Other format’ }
</td>
</tr>

But this is actually printing me result of f in the HTML … So i put it into an undisplayed html tag but it’s make me think there’s something better to do here…

Solution :

Just create a method and use it in the template:

methods: {

getFormat(width,height) {

var f = this.formats.find( e => {

return (e.shortEdge == height && e.longEdge == width) || (e.shortEdge == width && e.longEdge == height);

});

return f ? f.label : ‘Other format’

}

}
<tr v-for=”data in ajaxDatas”>
<td>
{ getFormat(data.width,data.height) }
</td>
</tr>

Solution 2:

Don’t do this in template you can filter out the data in computed property then in v-for use that computed property.As a rule of thumb always keep the template as simple as possible and all the complex logic will go in script (methods, computed props or life cycle hooks).

[Vue.js] Need to go through 2 objects at the same time with VUEJS

I just want to throught POSTS and USERINFO at the same pace, in a way that in show the right user avatar for a given post

Objects

posts : {!! $posts !!},
userinfo : {!! $userinfo !!},

Template

< v-cloak v-for=”post in posts”>
<div v-bind:style=”{ backgroundImage: ‘url(‘ + post.picture + ‘)’ }”>
<a href=”{– url(“#” v-bind:style=”{ backgroundImage: ‘url(‘ + userinfo.avatar + ‘)’ }”></a>
</div>

Dont know how… basicly…

Solution :

I think you can add a property id to the user object.
And a property userId to the post object to avoid mistakes.

User has to be a prop of the element to be used into it

Solution 2:

The correct way (IMHO) is to provide the data to the template in a correct way, so the template just loops through the data the least amount of time.

To support that a computed value may be the easiest way to implement.

You can create a complex loop using js in you computed value, and then you reduce any complex logic in the template. This may also reduce the number of renders or re-computations needed if other parts of the component or template are changing.

other options are to update data.variable using a watch or from an api callback

[Vue.js] How to make two inputs react to each other in Vue.js

when building a tool to calculate how much it would cost to buy certain material.
The problem is that sometimes the user buys it either by mass or volume.

I would like a way to have two active inputs (mass and volume) and each automatically updates considering the material density.

I tried computed properties and watchers but couldn’t make it work properly.

Here is what I’d like it to look like and what I tried
https://jsfiddle.net/yfuk958j/

Mass = <input v-model.number=”mass”> <br/>
Volume = <input v-model.number=”volume”><br/>

computed: {
volume() {
return this.mass * this.density
},
mass () {
return this.volume / this.density
}
}

Solution :

All you need is 2 inputs, each bound to a property of the vm. And a watch function to update any of them when the other changes:

Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: ‘#app’,
data: {
density: 1,
mass: 1,
volume: 1,
inputType: ‘mass’
},
watch: {
mass(val) {
this.volume = val/this.density;
},
volume(val) {
this.mass = val*this.density;
},
density(val) {
this.volume = this.mass/val;
}
},
methods: {
round(val) {
return Math.round(val * 1e3)/1e3
}
}
})
span {min-width: 100px; display: inline-block;}
input[type=”range”] {width: 200px;}
input[type=”number”] {width: 100px;}
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id=”app”>
<div>
<span>Density:</span> <input v-model=”density” type=”range” min=”.1” max=”10” step=”0.1”>{density}g/cm<sup>3</sup>
</div>
<div>
<div>
<span>Mass:</span> <input v-model=”mass” type=”range” min=”1” max=”1e4” step=”0.001”>
<input v-model=”mass” type=”number” min=”1” step=”0.1” max=”1e4”>g
[Volume: {round(volume)}cm<sup>3</sup>]
</div>
<div>
<span>Volume:</span> <input v-model=”volume” type=”range” min=”2” max=”1e4” step=”0.001”>
<input v-model=”volume” type=”number” min=”2” max=”1e4” step=”0.1”>cm<sup>3</sup>
[Mass: {round(mass)}g]
</div>
</div>
</div>

[Vue.js] Add content-encoding header on axios

I use API Gateway on AWS.

First, I activated CORS option and send a request on axios, then it worked.

And I activated content-encoding and I added axios option

axios.defaults.headers.post[‘Content-Encoding’] = ‘gzip’

Then CORS error occured.

How can I solve it?

Solution :

Did you add correct headers directly to the axios POST ?

Maybe you could try

axios.post(your-url, {
headers: {
‘Content-Encoding’: ‘gzip’
}
})

[Vue.js] v-text-field is not occupying the full width of the container

when making a form in a dialog. when trying to get a v-text-field occupy the full width of the container. But it is not occupying the full width.

I tried giving xs12 to lg12. I tried the directive full-width.

Here s my code:

<v-dialog v-model=”dialog” max-width=”878px”>
<template v-slot:activator=”{ on }”>
<v-btn color=”primary” dark class=”mb-2” v-on=”on”>
<span id=”two”>
<img id=”plus” src=”../assets/plus-symbol.svg”>
<span id=”addapp”>Add Application</span>
</span>

</v-btn>
</template>
<v-card style=”border-radius:20px 20px 0 0;”>
<v-card-title>
<span class=”headline” id=”frmttl”>{ formTitle }</span>
</v-card-title>

<v-card-text>

<v-container fluid grid-list-md>
<v-layout row wrap style=”margin-left:-600px; height: 314px; width:878px;”>

<v-flex xs12 sm12 md12 lg12 xl12 >
<v-text-field v-model=”editedItem.ApplicationName” single-line outline full-width placeholder=”New Application Name”></v-text-field>
</v-flex>
</v-layout>
</v-container>

</v-card-text>

<v-card-actions id=”crdactns”>
<v-spacer></v-spacer>
<v-btn id=”closbtn” flat @click=”close”>Close</v-btn>

<v-btn id=”savebtn” flat @click=”save”>{ CreateOrSave }</v-btn>
</v-card-actions>
</v-card>
</v-dialog>

I expect the v-text-box to occupy the full width of the dialog. But actually it is only occupying about half the space on the left side.

Solution :

Codepen : https://codepen.io/anon/pen/dLoNeO

remove “margin-left:-600px; height: 314px; width:878px; lines. will work fine. checked and working

[Vue.js] Dynamic header name refresh with Ag-Grid

there is a “select” column and to have the total of the current selected rows in the header name.

when using headerValueGetter but the value is not refreshed when a new row is selected.

// in my colDef
headerValueGetter: params => `(${this.totalSelected})`

// methods
onSelectionChanged(event) {
this.totalSelected = event.api.getSelectedNodes().length
},

totalSelected is a property of my vue.js component and its value is updated when a new row is selected.

Any ideas how to accomplish this ?

Solution :

Try refreshing the header manually in the selectionChanged-event:

onSelectionChanged(event) {
this.totalSelected = event.api.getSelectedNodes().length;
gridOption.api.refreshHeader();
},

[Vue.js] How to get object to use in v-bind, in v-for

Consider:

<ol class=”breadcrumb arr-right”>
<li v-for=”(url,name, index) in links” v-bind:class=” (index == (links.length -1)) ? ‘breadcrumb-item active’ : ‘breadcrumb-item’”>
<a v-bind:href=”url”>{ name }</a>
</li>
</ol>

The problem here is links.length is always undefined. Everything in this works fine except the ternary operation due to the undefined state of links. How do I access links from v-bind?

Solution :

Since links is an object, links.length will always be undefined because an object doesn’t have a length property (but an Array does).

You can determine the size of the object by its key length. Note that Object.keys() gives an Array of the object’s keys, so you could use Array.prototype.length on the result to get the object size.

const class = index === Object.keys(links).length - 1
? ‘breadcrumb-item active’
: ‘breadcrumb-item’

The syntax for the class binding is not quite correct.
You could combine object syntax and array syntax like this:

<li v-bind:class=”[ { ‘active’: index === Object.keys(links).length - 1 }, ‘breadcrumb-item’ ]“>

demo 1

Or just use object syntax:

<li class=”breadcrumb-item” v-bind:class=”{ ‘active’: index === Object.keys(links).length - 1 }”>

demo 2

But if the objective is to style the last <li> element, there might be a simpler way in CSS. Instead of applying .breadcrumb-item.active to the last item, use :last-of-type:

.breadcrumb-item:last-of-type {
/* the styles here */
}

demo 3

Solution 2:

Try this:

<ol class=”breadcrumb arr-right”>
<li v-for=”(item, index) in links” v-bind:class=” (index == (links.length -1)) ? ‘breadcrumb-item active’ : ‘breadcrumb-item’”>
<a v-bind:href=”item.url”>{ item.name }</a>
</li>
</ol>