link3151 link3152 link3153 link3154 link3155 link3156 link3157 link3158 link3159 link3160 link3161 link3162 link3163 link3164 link3165 link3166 link3167 link3168 link3169 link3170 link3171 link3172 link3173 link3174 link3175 link3176 link3177 link3178 link3179 link3180 link3181 link3182 link3183 link3184 link3185 link3186 link3187 link3188 link3189 link3190 link3191 link3192 link3193 link3194 link3195 link3196 link3197 link3198 link3199 link3200 link3201 link3202 link3203 link3204 link3205 link3206 link3207 link3208 link3209 link3210 link3211 link3212 link3213 link3214 link3215 link3216 link3217 link3218 link3219 link3220 link3221 link3222 link3223 link3224 link3225 link3226 link3227 link3228 link3229 link3230 link3231 link3232 link3233 link3234 link3235 link3236 link3237 link3238 link3239 link3240 link3241 link3242 link3243 link3244 link3245 link3246 link3247 link3248 link3249 link3250 link3251 link3252 link3253 link3254 link3255 link3256 link3257 link3258 link3259 link3260 link3261 link3262 link3263 link3264 link3265 link3266 link3267 link3268 link3269 link3270 link3271 link3272 link3273 link3274 link3275 link3276 link3277 link3278 link3279 link3280 link3281 link3282 link3283 link3284

[Vue.js] Why is this Vue computed property not reactive?

I’d like my view, using an id passed as a prop, to lookup an object’s property in the store. The object in the store appears asynchronously, so the object might not be present right away. I’d like the view to react to the object’s eventual appearance.

<template>
<div>
<h1>{ title }</h1>
</div>
</template>

<script>
export default {
props: [‘id’],
computed: {
widget () {
let path = `widget/${this.id}`
return this.$store.state.widgets[path]
},
title () {
let widget = this.widget
return (widget) ? widget.data().fullName : ‘nothing to see here’
}
}
}
</script>

Using vuex debug tools, I can watch the store widgets object start out empty and then get set with widgets: { ‘widgets/someId’: { … } }, but my vue.js doesn’t seem to pick up the change. The title remains == ‘nothing…’.

I tried making these methods, but I get the same behavior. I also tried replacing the whole widgets object on the store, instead of one prop at a time (I think that’s a requirement), but still no luck.

I think my question is very similar to this one, but the answer there is too terse. It just says “use a data item”, but I don’t really know what that is or how to use it (or why that will make the vue.js reactive).

Solution :

Mutations Follow Vue’s Reactivity Rules

Since you’re watching it go from empty to having some members, you are falling afoul of Vue’s change detection caveats.

vue.js cannot detect property addition or deletion.

You need to use Vue.set when adding or deleting members, even in Vuex.

Solution 2:

the widget is most likely not reactive, because widget itself does not change, and neither does widget.data because it is a function you define. vue.js does not “see” the changes in data when data is called, because it is a function.

You have several ways of making the widget reactive. One is by precomputing the data and returning an object without functions. This could mean a performance drop when you have a lot of widgets, even though you do not need the data in most of them.

Another one is by potentially using the relatively new getter function/method. You would get the data with widget.data and have a widget like

{
id: 1,
get data() {
// Whatever was in the function before
}
}

Remember that this is (I believe) an Ecmascript 6 feature, so you will likely need to run this through babel to be compatible with all relevant browsers.

[Vue.js] Vue Router previous page without reload

I’m trying to create a back button to go to the previous page using the vue-router in vuejs that would work exactly like the browser’s back button. The problem is, when using history mode for the router, when I do

this.$router.go(-1);

it actually refreshes the page, which is quite annoying, and the browser’s back button does not. If I remove history mode, it works as expected, exactly like the browser’s back button. However, in this case, I need to deal with the ugly hashtag in the URL. Also, since I only need this button for a few pages, I could also use keep history mode, but instead of making the back button actually go to the previous page, I could toggle around some values to change which dynamic component is shown, but not actually change the current page. However, if I do this, the browser’s back button wouldn’t work as expected anymore, since it clearly can’t toggle the state.

Is there any way to make a button that works exactly as the browser’s back button does? As in, make a back button that does not refresh the page, not have a hashtag in the URL, and still work with the browser back buttons?

EDIT:
Was going to delete since I realised it’s not a problem with the code, it’s a problem with the testing, but I’ll keep it here just in case it’s useful to someone. When I was going to my route with the back button, there was no button to go to that route, so I would need to directly enter it into the URL. However, this effectively wipes all the stored states, so my back button didn’t work properly. If I navigated to that page from another page, then my back button worked as expected.

Solution :

You can simulate hitting the browser’s back button directly with window.history.back().

Solution 2:

Try like that

this.$router.back()

[Vue.js] How to edit the template depending on what data there is?

there is a vue.js component that creates a <select> with <option>s. the options in the select to be dependent on a list.

Vue.component(‘column-header’, {
data: function() {
return {
options: [‘Name’, ‘Address’, ‘Email’, ‘Mobile’, ‘Card Number’, ‘Other’],
}
},
template: `<div class=”uk-width-1-5”>
<select class=”uk-select”>
{ options }
</select>
</div>`
});

new Vue({ el: ‘#app’ })

As I decide to expand my options list later, it should automatically insert the new item as an option. Is this the correct way to go about it?

Solution :

Use v-for to render a list of elements:

<option v-for=”option in options”>{option}</option>

The options data property is reactive, so adding items to that array would automatically update the template to include the new <option> in the <select>.

Vue.component(‘column-header’, {
data: function() {
return {
options: [‘Name’, ‘Address’, ‘Email’, ‘Mobile’, ‘Card Number’, ‘Other’],
}
},
template: `<div class=”uk-width-1-5”>
<select class=”uk-select”>
<option v-for=”option in options”>{option}</option>
</select>
<button @click=”addOption”>Add option</button>
</div>
`,
methods: {
addOption() {
this.options.push(‘Foo’ + this.options.length);
}
}
});

new Vue({ el: ‘#app’ })
<script src=”https://unpkg.com/vue@2.6.6"></script>

<div id=”app”>
<column-header></column-header>
</div>

Solution 2:

You can use v-for to iterate over the array and create new options.

<select>
<option v-for=”option in options” :key=”option”>{ option }</option>
</select>

[Vue.js] How to use Laravel Eloquent to fetch from two tables (Albums & Tracks)

there is two tables, albums and tracks and in my albums table there is this
albums = ‘id’, ‘title’,’artist_id’, ‘genre_id’, ‘track_id’
While in my tracks table there is this
tracks = ‘id’, ‘title’, ‘album_id’, ‘artist_id’

in my Album.php Model i have

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Album extends Model
{
public function artist()
{
return $this->belongsTo(‘App\Artist’);
}

public function genre()
{
return $this->belongsTo(‘App\Genre’);
}

public function track()
{
return $this->hasMany(‘App\Track’);
}
}

and in my Track.php Model i have

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Track extends Model
{
public function artist()
{
return $this->belongsTo(‘App\Artist’);
}
public function albums()
{
return $this->belongsTo(‘App\Album’);
}
}

In My Track Controller I have

<?php

namespace App\Http\Controllers;
use App\Track;
use App\Http\Resources\Track as TrackResource;

use Illuminate\Http\Request;

class TrackController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
// Get tracks
$tracks = Track::with(‘albums’)->get();

// Return collection of albums as a resource
return TrackResource::collection($tracks);
}

/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$track = new Track();

$track->title = $request->input(‘title’);
$track->album_id = $request->input(‘album_id’);
$track->artist_id = $request->input(‘artist_id’);
$track->duration = $request->input(‘duration’);
$track->release_date = $request->input(‘release_date’);
$track->track_position = $request->input(‘track_position’);
$track->track_link = $request->input(‘track_link’);

if($track->save()) {
return new TrackResource($track);
}else{
return “Error Saving”;
}
}

/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
// Get single track
$track = Track::findOrFail($id);

// Return single track as a resource
return new TrackResource($track);
}

/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}

/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}

/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
// Get single track
$track = Track::findOrFail($id);

if($track->delete()) {
return “deleted”;
}else{
return “Error Deleting”;
}
}
}

Album Controller I have

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Album;
use App\Http\Resources\Album as AlbumResource;

class AlbumController extends Controller
{
public function index()
{
// Get albums
$albums = Album::with(‘artist’)->orderBy(‘artist_id’, ‘desc’)->limit(8)->get();

// Return collection of albums as a resource
return AlbumResource::collection($albums);
}

public function store(Request $request)
{
$album = new Album();

$album->title = $request->input(‘title’);
$album->artist_id = $request->input(‘artist_id’);
$album->genre_id = $request->input(‘genre_id’);
$album->artwork_path = $request->input(‘artwork_path’);
$album->album_date = $request->input(‘album_date’);
$album->upc = $request->input(‘upc’);
$album->record_label = $request->input(‘record_label’);

if($album->save()) {
return new AlbumResource($album);
}else{
return “Error Saving”;
}
}

public function show($id)
{
// Get single album
$album = Album::findOrFail($id);

// Return single album as a resource
return new AlbumResource($album);
}

public function destroy($id)
{
// Get single album
$album = Album::findOrFail($id);

if($album->delete()) {
return “deleted”;
}else{
return “Error Deleting”;
}
}
}

I would like to display all the (tracks) related to an (album) under that album.

Solution :

You can do it by using relationships: Laravel eloquent relationships

Just add this function to the Album model:

public function tracks () {
return $this->hasMany(‘App\Track’);
}

And this to the Track model:

public function album () {
return $this->belongsTo(‘App\Album’);
}

That way you can get the tracks of a single album like this:

$tracks = App\Album::find($id)->tracks();

Solution 2:

<?php

class Album extends Entity
{
protected $table = ‘albums’;

public function tracks()
{
return $this->hasMany(Track::class);
}
}

class Track extends Entity
{
protected $table = ‘tracks’;

public function album()
{
return $this->belongsTo(Album::class);
}

public function artist()
{
return $this->belongsTo(Artist::class);
}
}

class Artist extends Entity
{
protected $table = ‘artists’;

public function tracks()
{
return $this->hasMany(Track::class);
}
}

// Get all traks of album :
$tracks = Album::find($id)->tracks();

// or all albums and their respective tracks :
$albums = Album::with(‘tracks’)->get();

// Get all traks of artist :
$tracks = Artist::find($id)->tracks();

// or all artists and their respective tracks :
$artists = Artist::with(‘tracks’)->get();

Know more about relationships here

Solution 3:

You can put the keys in the relationship’s function if you do not defined in the DB. Try to put another related key in relationship’s function like this

return $this->hasMany(‘App\Comment’, ‘foreign_key’, ‘local_key’);

For more information Eloquent Relationships

Hope it wiil be helpful to you :)

[Vue.js] Node - Attaching to server / websockets

when running a vue.js application (VUE-CLI 3) on Node. In dev mode, I run ‘npm run serve’ and the application is brought up and works as expected.

I would now like to add websocket code to the server.

Most examples I see have some setup code similar to:

const http = require(‘http’);
const server = http.createServer();
const wsServer = new WebsocketServer({httpServer: server});

When I run ‘npm run serve’ I now am greeted with the following error message:

‘http.createServer is not a function’

Is there a way to attach the websockets to the current running node server when invoked via npm run serve? In other words, can I skip the createServer call and attach it to whatever is currently running?

Solution :

Well, the code should read something like this…

var express = require(‘express’);
var app = express();
var http = require(‘http’);
var server = http.createServer(app);
var io = require(‘socket.io’).listen(server);

You will need to use ExpressJS on the back-end to handle messages.

[Vue.js] Vuejs2 - How to update the whole object from the server not losing reactivity?

there is a list of objects that can be updated from the database.

So, when I load the list, objects have only id and name.

When I click on an object I load other fields that can be of any length - that’s why I don’t load them with the objects in the list.

I found that when I update an object it can be difficult to keep reactivity https://vuejs.org/v2/guide/reactivity.html so I need to find some workaround.

this code works almost okay:

axios.get(‘/api/news’, item.id).then(function(response){
if (response){
Object.assign(item, response.data.item);
}
});

But the problem is the fields that have not been presented from the beginning is not 100% reactive anymore. What is going on is a new field has been updated reactively only when I change another, previous one. So, if I show 2 text field with old and new properties, if I change the second property, the field will not be updated until I change the first one.

I got item object from the component:

data () {
return {
items: [],
}
},

and

<div v-for=”item in items” @click=”selectItem(item)” >
<span>{item.name}</span>
</div>

Then item’s been passed to the function selectItem.

What is the proper pattern to load new fields and keep them reactive? (NB: it’s not the case when I can assign field by field - to reuse the same code no matter which object it is, so I need so the solution for updating an object at a time without listing all new fields.)

Note. This code works inside the component.

Solution :

Have a look at Change-Detection-Caveats vue.js cannot detect property addition or deletion if you use “normal assign” methods.
You must use Vue.set(object, key, value)
Try something like the following:

axios.get(‘/api/news’, item.id).then(function(response){
if (response){
let item = {}
Vue.set(item, ‘data’, response.data.item)
}
});

Than item.data would than be reactiv.

Solution 2:

Completely revised post: Ok, the example you give uses an array, which has its own caveats, in particular that you can’t directly set values like vm.items[indexOfItem] = newValue and have it react.

So you have to use Vue.set with the array as the first argument and the index as the second. Here’s an example that adds a name property to object items and then uses Vue.set to set the item to a new object created by Object.assign.

new Vue({
el: ‘#app’,
data: {
items: [{
id: 1,
other: ‘data’

}, {
id: 2,
other: ‘thingy’
}]
},
methods: {
selectItem(parent, key) {
const newObj = Object.assign({}, parent[key], {
name: ‘some new name’
});

Vue.set(parent, key, newObj);
setTimeout(() => {parent[key].name = ‘Look, reactive!’;}, 1500);
}
}
});
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id=”app”>
<div v-for=”item, index in items” @click=”selectItem(items, index)”>
<span>{item.name || ‘empty’}</span>
</div>
<pre>
{JSON.stringify(items, null, 2)}
</pre>
</div>

[Vue.js] State is changing on me inside mutation

when having a really weird issue with state changing inside a mutation(!). In my mutation when logging the following on the first two lines:

console.log(‘mutation state:’, state)
console.log(‘mutation state.game.gameTree[2]:’, state.game.gameTree[2])

Expected: that state.game.gameTree is the same

Actual: They are not! As you can see on the screenshot state.game.gameTree[2].activeActionId are not the same.

How can this value possibly change from line 1 to line 2? I hope someone can help :)

Solution :

Chrome displays the value of an object at the time you view it in the console, not at the time it is logged. I would try doing this:

console.log(‘mutation state:’, JSON.parse(JSON.stringify(state)))
console.log(‘mutation state.game.gameTree[2]:’, JSON.parse(JSON.stringify(state.game.gameTree[2])))

And if you still get the same issue, then something weird is going on.

For example, if you had:

function example() {
var a = { b: { c: 1 };
return function() {
a.b.c++;
return a;
}
}

var wtf = example()

console.log(wtf())
console.log(wtf())
console.log(wtf())

You’ll see here that it increments as expected. If you run it in chrome, you’ll see:

{b: {}
{b: {}
{b: {}

and when you then expand it, they would all show the same value.

Solution 2:

As dave already mentioned, if you hover over the i to the right of the expanded object, you will see that “it has been evaluated now”. In other words, it will check what the value is at the time you expand it, not what the value is when it was logged.

If you need to debug something that is changing rapidly, use a debugger statement. This will pause execution and shows the debugger statement in the source. You can hover over variables to see their content, or find a variable in some scope on the right hand side. You can step through the code to see how the variables change. If you log something, since the execution has stopped, the object will actually be evaluated at the time it was logged if you do:

console.log(x);
debugger;

[Vue.js] Using Value of Option in select in Vue

In the following:

<select id=”test”>
<option value=”1”>Test One</option>
<option value=”2”>Test Two</option>
</select>

is, When i select the option, The value of selected option should appear in input box. Like when i click Test One, the input box should say 1 as selected
Is it possible to do this in Vue?

Solution :

You have to used v-model to get the selected item from <select>

<select v-model=”selected”>
<option disabled value=””>Please select one</option>
<option>A</option>
<option>B</option>
</select>
<span>Selected: { selected }</span>

In Javascript

new Vue({
el: ‘…’,
data: {
selected: ‘’
}
})

I hope you got what you want!

Solution 2:

You can accomplish this by using the @change event handler

<select @change=”handleChange”>
<option
v-for=”item in options”
:value=”item.value”
v-text=”item.letter”
/>
</select>

new Vue({
el: “#app”,
data: {
selected: undefined,
options: [
{ letter: ‘A’, value: ‘1’ },
{ letter: ‘B’, value: ‘2’ },
]
},
methods: {
handleChange({ target: { value } }) {
this.selected = value
}
},
})

Check out this fiddle

[Vue.js] Data not refreshing from child component to parent

there is a child component that I add in links. Once completed I call the parent component to fetch the new links.

My links in the v-for aren’t updating. They are only updating when I reload the page with the new entry. Upon submit, my child component to notify/call the parents fetchLinks function to update all the links on the screen (Which its not updating, unless I refresh page)

This is on the form success function from Child AddLinksComponent

// Get the new updated subscriptions
this.$parent.fetchLinks()

Parent Component

<div class=”card card-body” v-for=”link in links” v-bind:key=”link.id”>
<h2>{ link.name }</h2>
</div>

<add-links></add-links>

export default {
data() {
return {
links: [],
}
},
components: {
‘add-links’: AddLinksComponent,
},
methods: {
fetchLinks() {

fetch(‘/links/‘)
.then(res => res.json())
.then(res => {
this.links = res.data
}).catch(err => {
console.log(‘Error’, err)
});
}
},
created() {
this.fetchLinks();
},
mounted() {

}
}

Solution :

In the child component try to emit an event to the parent one when the task is done like :

this.$emit(‘fetch’);

in the parent component :

<add-links @fetch=”fetchLinks”></add-links>

[Vue.js] Failed to generate render function SyntaxError Unexpected string in

ocaasionaly this error came when i wrote code for input tags for keyup and keypress event and their corresponding vue.js code it was working but when i wrote
next input tag for keydown event and their correspoding vue.js code i got an error
like

till two input there is run this code earlier so i removed my new code and their corresponding vue.js code and than i again run but now when still getting error in my correct previous code also

//leckeyboadevent.html

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8”>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0”>
<meta http-equiv=”X-UA-Compatible” content=”ie=edge”>
<title>Document</title>
<script src=”https://unpkg.com/vue@2.6.6/dist/vue.js"></script>
</head>
<body>
<div id=”myapp”>
<input type=”text” placeholder=”keypress” @keypress=”keypressfun” >
<br\>

<input type=”text” placeholder=”keyup” @keyup=”keyupfun”>
<br\>

<input type=”text” placeholder=”keydown” @keydown=”keydownfun”>

</div>
<script src=”lec6keyboardevent.js”></script>
</body>
</html>

//this my js file

var myapp=new Vue({
el:”#myapp”,
data:{

},
methods:{
keypressfun:function(event){
console.log(event.key);
},
keyupfun:function(event)//this works when key release
{
console.log(event);
},
keydownfun:function()
{
console.log(“keydown”);
}
}
});

when getting error
vue.js:634 [vue.js warn]: Failed to generate render function:

SyntaxError: Unexpected string in

with(this){return _c(‘div’,{attrs:{“id”:”myapp”},[_c(‘input’,{attrs:{“type”:”text”,”placeholder”:”keypress”},on:{“keypress”:keypressfun}),_v(“ “),_c(‘br’,{attrs:{“\“:””}),_v(“ “),_c(‘input’,{attrs:{“type”:”text”,”placeholder”:”keyup”},on:{“keyup”:keyupfun}),_v(“ “),_c(‘br’,{attrs:{“\“:””}),_v(“ “),_c(‘input’,{attrs:{“type”:”text”,”placeholder”:”keydown”},on:{“keydown”:keydownfun}),_v(“ “),_c(‘br’),_c(‘br’)])}

(found in <Root>)

Solution :

Hi @user9083922 I think the problem is how you are closing the html tags.
Have you tried to close the br tags this standard way <br/> instead of <br\>?

It should work with this change.

In addition, if you want, <br> tags doesn’t need to be closed in html5 as they are void elements.

For more info you can check:
https://www.w3.org/TR/html/syntax.html#writing-html-documents-elements