link3014 link3015 link3016 link3017 link3018 link3019 link3020 link3021 link3022 link3023 link3024 link3025 link3026 link3027 link3028 link3029 link3030 link3031 link3032 link3033 link3034 link3035 link3036 link3037 link3038 link3039 link3040 link3041 link3042 link3043 link3044 link3045 link3046 link3047 link3048 link3049 link3050 link3051 link3052 link3053 link3054 link3055 link3056 link3057 link3058 link3059 link3060 link3061 link3062 link3063 link3064 link3065 link3066 link3067 link3068 link3069 link3070 link3071 link3072 link3073 link3074 link3075 link3076 link3077 link3078 link3079 link3080 link3081 link3082 link3083 link3084 link3085 link3086 link3087 link3088 link3089 link3090 link3091 link3092 link3093 link3094 link3095 link3096 link3097 link3098 link3099 link3100 link3101 link3102 link3103 link3104 link3105 link3106 link3107 link3108 link3109 link3110 link3111 link3112 link3113 link3114 link3115 link3116 link3117 link3118 link3119 link3120 link3121 link3122 link3123 link3124 link3125 link3126 link3127 link3128 link3129 link3130 link3131 link3132 link3133 link3134 link3135 link3136 link3137 link3138 link3139 link3140 link3141 link3142 link3143 link3144 link3145 link3146 link3147 link3148 link3149 link3150

[Vue.js] VueJS / Vuetify - Possible to dynamically load a data table without having to hard-code the columns?

Good day,

In trying to learn VueJS I wanted to make a generic Vuetify Data Table that could receive an array of objects with n properties, where n is unknown.

Every example and article I’ve found about using these tables hard-codes the object properties into their headers and items slots, something like this:

<template slot=”items” slot-scope=”props”>
<td>{ props.item.name }</td>
<td class=”text-xs-right”>{ props.item.calories }</td>
<td class=”text-xs-right”>{ props.item.fat }</td>
<td class=”text-xs-right”>{ props.item.carbs }</td>
<td class=”text-xs-right”>{ props.item.protein }</td>
</template>

Which is fine if there is 1 or 2 datasets. But what if to load one of 100 different datasets into my data-table? Do I really need 100 different “foo-table” components with hard-coded values?

How do I handle the template interpolation that would allow me to reuse a single data-table component that could handle data like:

items: [{ name: ‘foo’, age: 100, occupation: ‘retired’ }, …]

and

items: [{ seq: ‘1234’, data: ‘XYZ’, flag: ‘N’, operator: ‘someone’, }, …]

and correctly v-for each <tr> by the item and the <td> by each item parameter as dictated by the headers (where item[n][header[i].value])?

What I’ve done so far.

I’ve spent a fair amount of time on this and the best I came up with is something like the following:

<template slot=’items’ slot-scope=’props’>
<tr v-for=’(item, i_index) in items’ :key=’i_index’>
<td v-for=’(header, h_index) in headers’ :key=’h_index’>
{ items[i_index][header.value] }
</td>
</tr>
</template>

But it doesn’t work because it’s producing items.length-times as many rows because I think the items slot is already implicitly doing a v-for inside of it, making my <tr v-for …> redundant.

Does anyone have any better ideas on how I can accomplish a generic data-table?

Solution :

I think the items slot is already implicitly doing a v-for inside of
it.

That’s correct, and you only one loop for each row:

<template slot=”items” slot-scope=”props”>
<td v-for=”header in headers”>{ props.item[header.value] }</td>
</template>

See this adapted pen from vuetify site. https://codepen.io/anon/pen/daQbrE?&editable=true&editors=101

[Vue.js] What is the correct way to retrieve data from 2 or more identical components?

Evening. I’ve created a button which adds a component that has an input field inside. I might need to press that button few times so there would be 2-3 input fields that appear. Whenever I type the text I would like to send a request from the parent component but I don’t know how to retrieve the data from every child component that has been created. Is this the time to start using vuex (never used it)?

ParentComponent.vue

<template>
<div>
<button class=”btn btn-success” @click=”addStep”>Add step</button>
<div v-for=”i in count”>
<recipe-step v-bind:step-number=”i”></recipe-step>
</div>
</div>
</template>

<script>
export default {
data() {
return {
count: 0
}
},
methods: {
addStep() {
this.count += 1;
}
}
}
</script>

StepComponent.vue

<template>
<div>
<div class=”from-group”>
<label for=”step-input”></label>
<input id=”step-input” v-model=”text” type=”text”>
</div>
</div>
</template>

<script>
export default {
props: {
stepNumber: {
type: Number,
required: true
}
},
data() {
return {
step: this.stepNumber,
text: “”
}
}
}
</script>

Solution :

No, you really don’t need Vuex yet. As long as you are still dealing with parent-child-component communication, you should be fine. Vuex comes into play when components, spread across the hole component hierarchy, need to exchange information.

Now, you should do something like this:

Don’t store the text in the child component. When the input changes, send a Custom Event right to the parent component. Note that

<input v-model=”text”>

is only syntax sugar for

<input :value=”text” @input=”text = $event”>

Both have the same effect. That’s way you can send the input event up to the parent, like this:

<input @input=”$emit(‘input’, $event)”>

Add another prop to the child component called value which should replace text.

And now you can use v-model in the parent component:

<recipe-step v-model=”text”>

To store multiple values, just use an array in the data properties.

<recipe-step v-model=”textArray[i]“>

Solution 2:

Vuex can help you on that, however if all you want is to get the input text value back to the parent with the minimum effort you can create a prop called value in the children and then pass it as v-model in the parent.

Since you have a v-for you could make it iterate over a list instead a counter and then pass some prop inside each item as v-model

[Vue.js] Update two data values using a Select input and v-model

there is a simple Select input, binded to a data property (device_id) using v-model:

<select v-model=”device_id”>
<option disabled value=””>Choose a device</option>
<option v-for=”device in devices” v-bind:value=”device.id”>
{ device.name }
</option>
</select>

When the user picks a device, this.device_id is updated automatically, which is great! I can then save that to my database.

However… I also want to save this.device_name and for the life of me, I can’t figure out how to “bind” or update both this.device_id AND this.device_name when the user clicks on an option.

I tried adding @click=”updateName(device.name)” to my <option> tag, and then that method would update the second data property.

However this only works on Firefox, since other browsers don’t trigger a click event on <option>. Besides it feels like kind of a weird/hacky way to do this.

Just to be clear, my question is: How can I update two data properties when the user clicks on an option?

when sure there is a “correct” way and I would love to hear the ideas! This feels like a very straightforward problem and yet I can’t seem to figure it out -_-

Thanks in advance!

Solution :

Try to bind the option value to the whole object and then work with properties of the selected one like :

<select v-model=”selected_device”>
<option disabled value=””>Choose a device</option>
<option v-for=”device in devices” v-bind:value=”device”>
{ device.name }
</option>
</select>

to send the id to the database just use this.selected_device.id and you could also use selected_device.name

[Vue.js] VueJS - create component programmatically by name

I’m trying to build a dynamic vue.js system, where to insert custom components knowing only their name. Inspiration from here took me to do:

export default {
name: ‘MySite’,
mixins: [MyMixin],
components: {MyComponent1, MyComponent2},

}

mounted() {

var ComponentClass = Vue.extend(MyComponent1)
var instance = new ComponentClass()
instance.$mount() // pass nothing
this.$refs.container.appendChild(instance.$el)
}

Now to do the same thing, but knowing only the component name ‘MyComponent1’ as String. What is the way to do it ? I guess it’s more related to pure JavaScript than Vue, but I can’t figure out how to do it.

Solution :

you are right is a simple js.

look at the example below, most importend thing is eval()

class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}

get getHeight() {
return this.height
}
}

// js string code
var code = “new Polygon(15, 200)”;
// convert it to code;
var cls = eval(code);

console.log(cls.getHeight)

Solution 2:

I found that using

this.$options.__proto__.components[‘MyComponent1’]

works and do what I want. Is it the cleanest solution ?

[Vue.js] How set calendar for Booking room hotel with node.js

I build website for user can create their room. Room info includes calendar which is array like:

{“date”:”15/02/2019”,”price”:58,”note”:””,”price_fee”:null} ,
{“date”:”16/02/2019”,”price”:58,”note”:””,”price_fee”:null} ,

Frontend load info of room. It will get all date from today to next 2 year, which means that calendar is array having about 256 x 3 = 1098 values.

How can I store it with mongoose ?

Solution :

Take a look at the Mongoose documentation, it provides a very straight-forward approach to creating the first schema and model.

[Vue.js] How to repeat jQuery press row effect in Vue.js?

There is a table there is found in codepen:
https://codepen.io/nikitamarcius/pen/LQOaxd

It is code example:

<div id=”app”>
<div class=”text-uppercase text-bold”>id selected: {selected}</div>
<table class=”table table-striped table-hover”>
<thead>
<tr>
<th>
<label class=”form-checkbox”>
<input type=”checkbox” v-model=”selectAll” @click=”select”>
<i class=”form-icon”></i>
</label>
</th>
<th>id</th>
<th>name</th>
<th>email</th>
</tr>
</thead>
<tbody>
<tr v-for=”i in items”>
<td>
<label class=”form-checkbox”>
<input type=”checkbox” :value=”i.id” v-model=”selected”>
<i class=”form-icon”></i>
</label>
</td>
<td>{i.id}</td>
<td>{i.name}</td>
<td>{i.email}</td>
</tr>
</tbody>
</table>
</div>

And script part:

new Vue({
el: “#app”,
data: () => ({
items: [
{
id: “id1”,
name: “John Doe”,
email: “email@example.com
},
{
id: “id2”,
name: “Jone Doe”,
email: “email2@example.com
}
],
selected: [],
selectAll: false
}),
methods: {
select() {
this.selected = [];
if (!this.selectAll) {
for (let i in this.items) {
this.selected.push(this.items[i].id);
}
}
}
}
});

You can see that while hover on it, an active column is indicating by a special color. What is the way to take data from a row the similar as it is made using jQuery events code: https://datatables.net/examples/advanced\_init/events\_live.html

So, once again, to make a functionality based on Vue.js code which will return row’s data when I press in any area of that row.

Solution :

Add a click event listener for each row at tr, and pass the row data to the event handler, for instance:

<tr v-for=”i in items” @click=”clickedRow(i.name)”>

methods: {

clickedRow(i) {
alert(‘clicked row’ + i)
}
}

https://codepen.io/anon/pen/qgQWZY

[Vue.js] How to deploy separated backend and frontend on same server

there is developed a project with Vuejs as the front-end and Laravel as the back-end api.In localhost they run in different ports.How should I deploy them in production?

Solution :

When you build the vue.js app for production, all the relevant files are in the dist folder. It does not run on any port, but instead the files are served by a webserver (e.g. Apache or Nginx). For a laravel api you normally have the public folder in the laravel installation visible, while having the rest of the files not directly accessible from the web.

when going to assume that you want to deploy the api and the frontend on the same domain. The easiest way of getting this to work is by having a specific prefix for the api. In the case below, I use the prefix /api for all api requests, since this is the default for api routes. Anything else is considered a request for the frontend.

You set up the folder structure like the following. The public_html folder is what is normally loaded when going to example.com and you can test this by adding a test.txt file with some content and going to example.com/test.txt. The backend folder contains the laravel installation. The frontend folder contains everything that the dist folder contained after running npm run build.

/var
+– /www
+– /vhosts
+– /example.com
+– public_html
+– /backend
+– /frontend

To get everything to work, we are going to remove the public_html folder and replace it with a symlink to backend/public.

cd /var/www/vhosts/example.com
rm -r public_html
ln -s ../backend/public public_html

When we check example.com, we now should see that we can make requests to the api using example.com/api/someroute. There are several ways we can make the frontend work with this, but for ease of deployment, lets create a symlink to the dist folder.

cd /var/www/vhosts/example.com/public_html
ln -s ../../frontend/dist app

If you are using hash mode for the vue.js application and don’t mind accessing the app through example.com/app, I believe this is all you would need to do. Otherwise you would need to modify the .htaccess file if you are using Apache, or change the rewrite configuration of whatever other webserver you are using. I imagine the .htaccess file would look something like this:

# We assume that the FollowSymLinks option is enabled in the main Apache configuration.
RewriteEngine On

# Rewrite anything that starts with `api` to the laravel index file
RewriteCond %{REQUEST_URI} ^/api
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

# Rewrite anything else to the frontend app
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /app/index.html [L]

[Vue.js] Show Div When Hover Based on ID in Vue JS

there is a div that when hover to it, it will show other div. However, my first div is dynamic, it has an ID. So how will i able to hover to ID based on its ID?

It should be @mouseenter=”hoverService{services.id} = true” but it causes error. So i made the code below to just static.

Here’s my code below:

<template>
<div
class=”col-md-3”
v-for=”(services, index) in servicesFiltered”
:key=”index”
@mouseenter=”hoverService = true”
@mouseleave=”hoverService = false”
\>
<div class=”service_background” v-if=”hoverService”>
<div class=”mb-1” v-for=”(sub_services, index) in services.menu_items” :key=”index”>
<router-link
:to=”{ path: `/${sub_services.data}`}”
\>
<a
href=”#”
class=”btn btn-outline-primary w-100 services_button”
\>{sub_services.text }</a>
</router-link>
</div>
</div>
</div>
</template>

<script>
export default {
data() {
return {
hoverService: false
};
}
};
</script>

Solution :

Try this code

https://codesandbox.io/s/y7p9qyyovz

You need to maintain hover for each item you can not manipulate using single variable for multiple items.

[Vue.js] Should I independently version Vue.js single-file components?

there is a sense that it would be prudent to use semver to version my components individually, seeing that the props they expect form a sort of contract. Are there any best practices in this regard? Am I overthinking this?

Solution :

Depending on what the needs are.
If the components are part of one library you should version them altogether as one package.

If you are using monorepo like lerna and publishing them as separate npm packages then it’s a good idea to version them separately

[Vue.js] How to add a new node in <v-treeview> Vuetify

I’m currently making a tree view using Vuetify. The tree view uses this structure:

items: [
{
id: 1,
name: ‘Applications :’,
children: [
{ id: 2, name: ‘Calendar : app’ },
{ id: 3, name: ‘Chrome : app’ },
{ id: 4, name: ‘Webstorm : app’ }
]
},
{
id: 5,
name: ‘Documents :’,
children: [
{
id: 6,
name: ‘vuetify :’,
children: [
{
id: 7,
name: ‘src :’,
children: [
{ id: 8, name: ‘index : ts’ },
{ id: 9, name: ‘bootstrap : ts’ }
]
}
]
},
{
id: 10,
name: ‘material2 :’,
children: [
{
id: 11,
name: ‘src :’,
children: [
{ id: 12, name: ‘v-btn : ts’ },
{ id: 13, name: ‘v-card : ts’ },
{ id: 14, name: ‘v-window : ts’ }
]
}
]
}
]
},
{
id: 15,
name: ‘Downloads :’,
children: [
{ id: 16, name: ‘October : pdf’ },
{ id: 17, name: ‘November : pdf’ },
{ id: 18, name: ‘Tutorial : html’ }
]
},
{
id: 19,
name: ‘Videos :’,
children: [
{
id: 20,
name: ‘Tutorials :’,
children: [
{ id: 21, name: ‘Basic layouts : mp4’ },
{ id: 22, name: ‘Advanced techniques : mp4’ },
{ id: 23, name: ‘All about app : dir’ }
]
},
{ id: 24, name: ‘Intro : mov’ },
{ id: 25, name: ‘Conference introduction : avi’ }
]
}
]
})

And it will look like this:

My problem is in adding a new node to this structure, For example if to add a child under applications then the code would probably look like this:

this.items[0].children.push(newObject)

Or if to add under src? then it might look like this:

this.items[1].children[0].children.push(newObject)

If to go deeper then it might look like this:

this.items[0].children[0].children[0].children[0].children[0].children.push(newObject)

As you can see, the way I add a node varies and the code changes depending on the location and depth of where to add the node. That means there is no single code that will cater for all the locations. Also I can add and nest as many node as I can. example is google drive How should I go about this? I’ve run out of ideas and is looking for any suggestions that might help.

Solution :

If you are adding nodes directly from the tree, the easiest way is by using scoped slots. For example, you can use the append slot to add something to each item. Since the item is passed to the slot, you can pass it to a function that can easily add a child to that object.

<v-app>
<v-treeview :items=”items”>
<template slot=”append” slot-scope=”{ item }”>
<v-btn @click=”addChild(item);”>Add child</v-btn>
</template>
</v-treeview>
</v-app>

addChild(item) {
if (!item.children) {
this.$set(item, “children”, []);
}

const name = `${item.name} (${item.children.length})`;
const id = this.nextId++;
item.children.push({
id,
name
});
}

Otherwise just walk recursively through the tree until you find the item you want to add to.

findItem(id, items = null) {
if (!items) {
items = this.items;
}

return items.reduce((acc, item) => {
if (acc) {
return acc;
}

if (item.id === id) {
return item;
}

if (item.children) {
return this.findItem(id, item.children);
}

return acc;
}, null);
}

You can see an example in codesandbox.