link685 link686 link687 link688 link689 link690 link691 link692 link693 link694 link695 link696 link697 link698 link699 link700 link701 link702 link703 link704 link705 link706 link707 link708 link709 link710 link711 link712 link713 link714 link715 link716 link717 link718 link719 link720 link721 link722 link723 link724 link725 link726 link727 link728 link729 link730 link731 link732 link733 link734 link735 link736 link737 link738 link739 link740 link741 link742 link743 link744 link745 link746 link747 link748 link749 link750 link751 link752 link753 link754 link755 link756 link757 link758 link759 link760 link761 link762 link763 link764 link765 link766 link767 link768 link769 link770 link771 link772 link773 link774 link775 link776 link777 link778 link779 link780 link781 link782 link783 link784 link785 link786 link787 link788 link789 link790 link791 link792 link793 link794 link795 link796 link797 link798 link799 link800 link801 link802 link803 link804 link805 link806 link807 link808 link809 link810 link811 link812 link813 link814 link815 link816 link817 link818 link819 link820 link821

[Vue.js] Should I be storing all my Vue methods and data in one file? Subscribe to RSS

I’m currently using vue.js on my web app for object oriented form validation, so that all I need is back-end validation and vue.js takes care of the rest.

This means that if my app has a lot of forms, forms that are mostly just page specific, I end up with a lot of methods and data in my vue.js instance.

new Vue({
el: ‘#mainDiv’,

data: {
profile_text: ‘’,
name: ‘’
//LOTS OF DATA THAT I’M LEAVING OUT
errors: new Errors()
},

methods: {
onSubmitSettings() {
axios.post(‘/settings’, this.$data)
.then(response => alert(‘Success!’))
.catch(error => this.errors.record(error.response.data.errors));
},
onSubmitCreate() {
axios.post(‘/subchannel/create’, this.$data)
.then(response => alert(‘Success!’))
.catch(error => this.errors.record(error.response.data.errors));
},
//LOTS OF METHODS THAT I’M LEAVING OUT
}
});

and this is all stored in one JS file.

Should I keep doing it like this? Or should I be storing methods/data meant for only one page to be stored on that page somehow?

Solution :

Assuming that the code you shared is the main/root vue.js instance, it probably is a bad practice to put all these in a single component.

Ideally, the code should have segregation of components between views and components. views are like individual pages which contain most of the business logic whereas components are reusable items like checkboxes, lists, inputs, etc..

The reasons for dividing the app into smaller views are:

Putting everything in a root instance will make the components less-reusable. They are depending on some sort of global state.
This makes modifications harder to track; overall making code less maintainable within the team.
Splitting into smaller views/components will allow you to use other ecosystem tools like vue-router which will further help in maintaining URLs, URL history, etc.
Segregation into smaller components will enable Vue.js to better track change detection producing efficient and performant view updates. UI updates become significantly faster.

In a nutshell, it is about following classical software engineering principles like SOLID, loose coupling, etc. This, in general, is not just confined to Vue.js.

[Vue.js] Send array data to laravel controller with Vue Subscribe to RSS

I’m stuck at my coding. How do i send the array data to the Laravel controller? Usually i bind the data to a form using this.form.something=”” then send them to the controller using axios, but how to do it with array? Should i use form or is there a way to send them without using form? Thanks.

vue.js Componenet

<template>
<form submit.prevent=”submitData”>
<div class=”jumbotron bg-dark col-md-10 offset-md-1”>
<div class=”card card-body bg-dark” v-for=”(user,index) in users” :key=”index”>
<h5>
<span class=”badge badge-success mb-3 float-left”>Data {index+1}</span>
<span style=”cursor:pointer” class=”float-right badge badge-danger mb-3” @click=”deleteData(index)”>X</span>
</h5>
<div class=”row”>
<div class=”form-group col-md-3”>
<label for=”email” class=”text-white”>Username:</label>
<input type=”text” class=”form-control” id=”username” v-model=”user.username”>
</div>
<div class=”form-group col-md-3”>
<label for=”pwd” class=”text-white”>Password:</label>
<input type=”password” class=”form-control” id=”password” v-model=”user.password”>
</div>
<div class=”form-group col-md-3”>
<label for=”pwd” class=”text-white”>Phone Number:</label>
<input type=”text” class=”form-control” id=”phone” v-model=”user.phone”>
</div>
<div class=”form-group col-md-3”>
<label for=”pwd” class=”text-white”>Email</label>
<input type=”email” class=”form-control” id=”email” v-model=”user.email”>
</div>
</div>
</div>
<br>
<button class=”btn btn-secondary float-right” @click=”addMoreData()” title=”Click to add row”><span class=”fa fa-plus-square”></span>  Add More Data</button>
</div>

<div class=”jumbotron bg-dark col-md-10 offset-md-1 “>
<button class=”btn btn-success col-md-6 offset-md-3 p-3” type=”submit”><span class=”fa fa-plus-square”></span>  Export to Microsoft Excel</button>
</div>
</form>

Script

<script>
export default {
data(){
return{
users: [{
username:’’,
password:’’,
phone:’’,
email:’’
}]
}
},
methods:{
addMoreData(){
this.users.push({
username: ‘’,
password: ‘’ ,
email: ‘’,
phone:’’
});
},
deleteData(index){
this.users.splice(index,1)
},
submitData(){

}
},
mounted() {
console.log(‘Component mounted.’)
}
}

Solution :

the code looks fine, just need to send the array to Laravel. Here’s an example:

submitData(){
// Here we send the data to ‘/users/store’ route,
// using POST method and ‘this.users’ array as data
axios.post(‘/users/store’, this.users)
.then(function (response) {
// If the request is successful, we can do whatever we want with the response here
console.log(response);
})
.catch(function (error) {
// If there’s an error, treat it here
console.log(error);
});
}

Still using the above example, in the UserController you would receive the data like this:

public function store(Request $request)
{
/*
$request->all() contains all the data you sent
in this case, the users array, but you should always
validate it before, using FormRequest, for example:
https://laravel.com/docs/5.8/validation#form-request-validation
*/
User::create($request->all()); // Here we save all users to database

// returning the data you sent before, just for testing.
return response()->json([$request->all()]);
}

[Vue.js] Vue - Array dosen't update Subscribe to RSS

On click, to push to array. It works if I manually refresh the vue.js extension in the console of Google Chrome but otherwise not

completeStep(index, key) {
let currentSet = index + key

if (this.exercise_completed[index].indexOf(currentSet) === -1) {
this.exercise_completed[index].push(currentSet)
} else {
this.exercise_completed[index].splice(this.exercise_completed[index].indexOf(currentSet), 1)
}
}

Solution :

maybe try to use this.$forceUpdate(); when you make the change.

https://vuejs.org/v2/api/#vm-forceUpdate

Hope this helps

Solution 2:

I would recommend making a key and changing the key on changes in the array. See here:
https://michaelnthiessen.com/force-re-render

[Vue.js] How do you dynamically create multiple bootstrap cards with Vue Subscribe to RSS

to use the bootstrap cards with vue.js dynamically. With Bootstrap Vue, to create a card I can do the following.

<b-card title=”Title” img-src=”https://placekitten.com/500/350" img-alt=”Image” img-top>
<b-card-text>
{getBlogOfType(“Vue”)}
</b-card-text>
<b-card-text class=”small text-muted”>Last updated 3 mins ago</b-card-text>
</b-card>

What to be able to do is create the number of cards based on the number of blogs there is from a database. there is my project linked to Firebase and when able to access the content. there is written a method “getBlogOfType(param)” to get the blog from firebase. As shown above I can call the method multiple times to get the blog I want, but how can I achieve this without manually creating a separate card every time?

Solution :

Once you have a variable set aside for the data, for example var posts = […];, you can use VueJs’s v-for as follows:

<b-card v-for=”post in posts” title=”Title” img-src=”https://placekitten.com/500/350" img-alt=”Image” img-top>
<b-card-text>
{getBlogOfType(“Vue”)}
</b-card-text>
<b-card-text class=”small text-muted”>Last updated 3 mins ago</b-card-text>
</b-card>

And use access the values of each element via the post object (post.title).

[Vue.js] How to style odd rows in a table in this vue.js example? Subscribe to RSS

when trying to add style to every odd number of rows in a table. But the example below fails.

template: `
<div container>
<h3>test title</h3>
<table :style=”overviewStyle”>
<div :class=”emptyDiv” v-for=”item in testlist”>
<tr>
<td :style=”{‘tdStyle’: index % 2 === 0, ‘tdGray’: index % 2 !== 0 }”>[[ item.result ]]</td>
</tr>
</div>
</table>
</div>
`,

computed: {
tdStyle() {
return {
‘border’: ‘1px solid #C0C0C0’,
‘padding’: ‘8px’,
};
},
tdGray() {
return {
‘background-color’: gray,
};
},

What’s interesting to me is this example works with class.

<td :class=”{‘tdStyle’: index % 2 === 0, ‘tdGray’: index % 2 !== 0 }”>[[ item.result ]]</td>

So works with :class but not :style.

If there is not an easier solution, is there a way I can move this logic into a function and then call the function to color odd rows?

Solution :

You can do that in pure CSS. There is absolutely no reason to put this in conditional code or JavaScript, which makes it much harder to maintain. vue.js has a way to combine HTML templates, JSS and CSS into components but I’m no expert on that aspect.

.zebra tr:nth-child(even) {
background: #eee;
}
.zebra tr:nth-child(odd) {
background: #ccc;
}
<table class=”zebra”>
<tr><td>foo
<tr><td>bar
<tr><td>baz
<tr><td>fizz
<tr><td>buzz
</table>

As to specifically why the code didn’t work, vue.js uses :class to add classes conditionally. When passing a JavaScript object to :class, each key is understood as a class name, which is present if its value is true.

The :style attribute has a different special behavior where each key of the object passed is a CSS attribute. This is useful if, for example, you want to always set an attribute on an element, but its value is conditional.

the code uses :style with things that aren’t CSS attributes.

<td :style=”{‘tdStyle’: index % 2 === 0, ‘tdGray’: index % 2 !== 0 }”>

If you wanted to use it without setting up a CSS class, you’d need to do something like this. It’s been a while since I haven’t done vue.js though, and I would strongly advise against putting this kind of logic in HTML attributes.

<td :style=”{‘background’: index % 2 === 0 ? ‘#eee’ : ‘#ccc’ }”>

Finally, the code is not even valid HTML with a div inside a table, which most certainly will cause issues as the browser doesn’t know where to put the div and where to put the tbody.

Solution 2:

While as the previous answer mentioned, yes you could probably do this using pure CSS (better IMO too), just wanted to answer the question on why class binding works but style does not.

If you look at the vue.js docs, you will see that the syntax for style is not correct. For class, what you have is correct and it should look like this:

<div :class=”{ active: isActive }”></div>

However, for binding style, you actually have to return the CSS styles as an object:

<div v-bind:style=”{ color: activeColor, fontSize: fontSize + ‘px’ }”></div>

So in the scenario, the style object becomes this (assuming on an even index):

{
tdStyle: true,
tdGrey: false
}

This is obviously not valid CSS. If you want to actually put the values of the functions, I suggest you use the spread operator for object destructuring in ES6, and for a cleaner code, use the JS ternary operator as well:

<td :style=”{ index % 2 === 0 ? …tdStyle : …tdGray }”>

Alternatively, if you don’t want to add any more styles, you can omit the object syntax completely and use this:

<td :style=”index % 2 === 0 ? tdStyle : tdGray”>

In here, what basically happens is the binding says “if index is even, then return the result of tdStyle function, else return the result of tdGray function”.

But of course as mentioned just CSS is the superior solution here. If you really want add some special styling that CSS can’t help with, you are still better off using class binding instead of style, that way the CSS can live inside the style tag of the component:

<td :class=”index % 2 === 0 ? ‘tdStyle’ : ‘tdGray’”>

[Vue.js] How to configure the routes so that my spa starts in the path /admin? Subscribe to RSS

I try to create a basic spa, but to use the basic authentication of laravel and not create a login system in vue, after logging in, it redirects me to the route /admin where it to be the entry point of my spa, try with this configuration and it shows nothing.

web.php -> routing

Route::get(‘/admin/{any}’,function(){
return view(‘app’);
})->where(‘any’,’.*‘)->name(‘admin’)->middleware(‘auth’);

Route::get(‘/admin’,function(){
return view(‘app’);
})->name(‘admin’)->middleware(‘auth’);

Route::get(‘/‘, ‘Auth\LoginController@showLoginForm’)->name(‘showLoginForm’);
Route::post(‘login’, ‘Auth\LoginController@login’)->name(‘login’);
Route::post(‘logout’, ‘Auth\LoginController@logout’)->name(‘logout’);

in my app view, there is the app file compiled with the following routes

const routes = [

{
path: ‘/admin’,
component: () => import(/* webpackChunkName: “routes” */`~/Pages/Layouts/Admin`),
meta: { requiresAuth: true },
children: [
{
path : ‘/‘, name : ‘Home’,
component: () => import(/* webpackChunkName: “routes” */`~/Pages/Admin/Home`),
meta: { },
},
{
path : ‘usuarios’,
component: () => import(/* webpackChunkName: “routes” */`~/Pages/Admin/Usuarios/Index`),
meta: { },
children : [
{

}
]
},

{
path: ‘403’,
name:’403’,
component: () => import(/* webpackChunkName: “routes” */`~/Pages/Errors/403`)
},
]
},

]

export default routes;

the routes I’m looking for is misite.com/admin/users for example, of course the path users would be a route of my vueRouter

Solution :

If you are going to redirect the users after login with auth laravel system to /admin path, just go to App\Http\Controllers\Auth\LoginController and edit the $redirectTo attribute like this:

$redirectTo = ‘/admin’

as mentioned in laravel doc :

When a user is successfully authenticated, they
will be redirected to the /home URI. You can customize the
post-authentication redirect location by defining a redirectTo
property on the LoginController, RegisterController, ResetPasswordController, and VerificationController.

for more information please check the doc Path Customization
Laravel after login

Solution 2:

You can try this in web.php file.

Route::any(‘/admin/{all}’, function () {
if ( ! Auth::user() ){
return redirect(‘/login’);
}
return view(‘admin’); //SPA app
})
->where([‘all’ => ‘.*‘]);

Also, in the vue.js routes, you need to use entrypoint of the URL /admin in path like this. This is just an example for moving to dashboard like /admin/dashboard

const routes = [
{
path: “/admin/dashboard”,
component: Dashboard,
name: “dashboard”,
meta: {
title: “Dashboard”,
requiresAuth: true
}
}
];

[Vue.js] Why is Vue changing the parent value from a child without emitting an event Subscribe to RSS

when fairly new to vue.js but doesn’t this behavior completely contradict the design of props down, events up?

there is managed to stop it by using Object.assign({}, this.test_object ); when initializing the value in child-component but shouldn’t that be the default behaviour?

Here is some background.

when trying to have a dirty state in a much larger application (Eg a value has changed so a user must save the data back to the database before continuing on their way)

I had an event being emitted, and caught by the parent but the code I had to test the value and init the dirty state was not running as the value had already been changed in the parent component.

Vue.component( ‘parent-component’, {
template: ‘#parent-component’,
data: function() {
return {
testObject: {
val: ‘Test Value’
}
}
}
});

Vue.component( ‘child-component’, {
template: ‘#child-component’,
props: {
test_object: Object
},
data: function() {
return {
child_object: this.test_object
}
}
});

Vue.config.productionTip = false;

new Vue({
el: ‘#app’,
});
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<script type=”text/x-template” id=”parent-component”>
<div>
<child-component :test_object=”testObject”></child-component>

<p>This is in the parent component</p>
<p><code>testObject.val = {testObject.val}</code></p>

</div>
</script>

<script type=”text/x-template” id=”child-component”>
<div>
<label for=”html_input”>HTML Input</label>
<input style=”border:1px solid #CCC; display:block;” type=”text” name=”html_input” v-model=”child_object.val” />
</div>
</script>

<div id=”app”>
<parent-component></parent-component>
</div>

Solution :

Use of v-model is a very deceptive thing. If you are not careful, you might end-up mutating data that doesn’t belong to the component. In the case, you are accidentally passing read-only props directly to the v-model. It doesn’t know if it is a prop or a local component state.

What you are doing is the right solution but considering one-way/unidirectional data flow in mind, we can rewrite this example in more explicit and elegant fashion:

the component definition would be:

Vue.component( ‘parent-component’, {
template: ‘#parent-component’,
data: function() {
return {
testObject: {
val: ‘Test Value’
}
}
},

methods: {
// Added this method to listen for input event changes
onChange(newValue) {
this.testObject.val = newValue;

// Or if you favor immutability
// this.testObject = {
// …this.testObject,
// val: newValue
// };
}
}
});

the templates should be:

<script type=”text/x-template” id=”parent-component”>
<div>
<child-component :test_object=”testObject”
@inputChange=”onChange”></child-component>

<p>This is in the parent component</p>
<p><code>testObject.val = {testObject.val}</code></p>

</div>
</script>

<!– Instead of v-model, you can use :value and @input binding. –>
<script type=”text/x-template” id=”child-component”>
<div>
<label for=”html_input”>HTML Input</label>
<input type=”text” name=”html_input”
:value=”test_object.val”
@input=”$emit(‘inputChange’, $event.target.value)” />
</div>
</script>

Key things to note:

When using v-model, ensure that you are strictly working on a local value/data of the component. By no means, it should be referenced copy of external prop.
A custom form-like component can be readily converted into the one that can work with v-model provided you accept current value as :value prop and event as @input. v-model will just work out of the box.
Any modification to the value should happen in the same component.

[Vue.js] Dynamically add rows to form using Vue.JS Subscribe to RSS

I’m trying to make a dynamic form using Vue. User clicks the add button and another row appears for them to add data. The problem is, i initially set only 1 row at first but , when i put the v-for on the div, 3 extra rows started appearing. I’m confused as to why that happened? Plus, nothing happen when i click the add button. Thanks.

Dynamic vue.js form

Componenet

<div class=”container”>
<title>exportDATA | Web to Excel</title>
<div class=”mt-4”>
<div class=”jumbotron bg-dark col-md-10 offset-md-1”>
<div class=”card card-body bg-dark” v-for=”(user,index) in users” :key=”index”>
<form>
<div class=”row”>
<div class=”form-group col-md-3”>
<label for=”email” class=”text-white”>Username:</label>
<input type=”text” class=”form-control” id=”username” v-model=”user.username”>
</div>
<div class=”form-group col-md-3”>
<label for=”pwd” class=”text-white”>Password:</label>
<input type=”password” class=”form-control” id=”password” v-model=”user.password”>
</div>
<div class=”form-group col-md-3”>
<label for=”pwd” class=”text-white”>Phone Number:</label>
<input type=”text” class=”form-control” id=”phone” v-model=”user.phone”>
</div>
<div class=”form-group col-md-3”>
<label for=”pwd” class=”text-white”>Email</label>
<input type=”email” class=”form-control” id=”email” v-model=”user.email”>
</div>
</div>
</form>
</div>
<br>
<button class=”btn btn-secondary float-right” title=”Click to add row”><span class=”fa fa-plus-square” @click=”addMoreData(index)” v-show=”index == users.length-1”></span>  Add More Data</button>
</div>

<div class=”jumbotron bg-dark col-md-10 offset-md-1 “>
<button class=”btn btn-success col-md-6 offset-md-3 p-3”><span class=”fa fa-plus-square”></span>  Export to Microsoft Excel</button>
</div>
</div>
</div>

Script

export default {
data(){
return{
users:{
username:’’,
password:’’,
email:’’,
phone:’’
}
}
},
methods:{
addMoreData(index){
this.users.push({
username: ‘’,
password:’’,
email:’’,
phone:’’
});
}

},
mounted() {
console.log(‘Component mounted.’)
}
}

Solution :

the data should be an array that contains objects as items. In the example, v-for directive iterate properties in one object.

data(){
return{
users: [{
username:’’,
password:’’,
email:’’,
phone:’’
}]
}
},

[Vue.js] Use mongodb in nuxt Subscribe to RSS

when trying to use MongoDB for long term and complex storage that Vuex isn’t suited for.

there is MongoDB installed and running and I installed the mongoose package.

In my plugins folder, there is a create a script that initializes the module and exports it:

plugins/mongoose.js

const mongoose = require(‘mongoose’);

mongoose.connect(‘mongodb://localhost/users’, { useNewUrlParser: true });

export default({ app }, inject) => {

inject(‘mongoose’, mongoose);

}

and then in my nuxt.config.js, I declare the module and set it as server side only.

nuxt.config.js


plugins: [
{ src: ‘~/plugins/mongoose.js’, mode: ‘server’ },
],

and then finally, in one of my pages I try to access it in a method.

pages/users.vue

<template>
<button @click=”addUser(‘joe’)”>Joe</button>
</template>

<script>
export default {
methods: {
addUser(name) {
console.log(this.$mongoose);
}
}
}
</script>

and when I click the button in the console I get cannot stringify a function change and then cannot stringify a function name. I can’t tell if this is working but I can’t use any properties of the mongoose object.

There doesn’t seem to be much structured information on this topic even though it seems like it would be fairly common.

Solution :

You cant do it like this. Nuxt is frontend. So the code will be executed on client in their browsers. the event will be executed in browser when user click on button. So you cant access mongoose there. mongoose dont work in browser, only in node.

So you need to have backend that will do the mongoose stuff and send\recieve data from the nuxt there using REST or GraphQL or whatever

[Vue.js] How do I bind a style to my v-for loop in this example? Subscribe to RSS

What am I doing wrong here? There is no error - but there is also no style being applied when I look via dev tools.

<!– Template –>
<td v-for=”steps in item.steps” v-bind:style=”steps.name”>
{ steps.name }
</td>

// Component definition
computed: {
endstage() {
return {
‘background-color’: ‘#f9f9f9’,
};
}
}

steps.name prints and if I bind class to steps.name that works - so not sure what I’m doing wrong with trying to bind style.

update:

In my template, I also am using this example which works fine:

<!– Template –>
<table :style=”tableStyle”>

// Component definition
computed: {
tableStyle() {
return {
‘background-color’: ‘#f9f9f9’,
‘border-color’: ‘#C0C0C0’,
‘padding’: ‘8px’,
‘color’: ‘red’,
‘width’: ‘100%’,
‘display’: ‘table’,
‘border’: ‘1px solid #ddd’,
};
}
}

So why can I not do the same for td using steps.name which in this example results in ‘endstage’?

Solution :

The output of the template will be something like this:

<td style=”endstage”>
endstage
</td>

I’m assuming that isn’t what you want as endstage is not a valid value for the style attribute. Note that the computed property isn’t being used at all here. It is just trying to set the style to the string ‘endstage’.

I guess what you’re trying to do is this?

<td v-for=”steps in item.steps” :style=”this[steps.name]“>

Assuming steps.name is ‘endstage’, this will use the object returned by the computed property endstage as the style. this[steps.name] evaluates as this[‘endstage’], which is just this.endstage.

It’s not a great strategy though as it assumes that all names will have their own computed properties.

If endstage is the only name you care about then you could do something like this:

<td v-for=”steps in item.steps” :style=”steps.name === ‘endstage’ ? endstage : null”>

If there are others then it’d be better to use a method:

<td v-for=”steps in item.steps” :style=”getStyle(steps.name)”>

with:

methods: {
getStyle (name) {
switch (name) {
case ‘endstage’:
return {‘background-color’: ‘#f9f9f9’}
// Other cases here
}
}
}

Solution 2:

It must be v-bind not v:bind.