Software

[Rails][Vue] Empty array returned when fetching the children nested within a parent component. Any idea why is this happening?

Vuejs - Mon, 2017-09-11 02:04

I'm using Rails 5.1 + Webpack running Vue 2. I'm fairly new to Vue, not so new to Rails.

I'm building a navbar component starting from the Bulma navbar. My objective is to be able to dynamically create links in the navbar by simply adding a navlink element nested within.

In my application.html.erb I have already created this structure (navlink nested inside navbar).

In hello_vue.js I'm initializing the Vue components and assigning them to a root element (one for the navbar and one for the rest of the content).

In navbar.vue, I'd like to iterate through all the and create a menu item accordingly. In order to do so, I added an empty navlinks data to navbar that I want to populate once it gets mounted() by fetching all its children (the nested navlink tags).

This is however not working, whenever I reference this.$children I get an empty array. Any idea why is this happening?

This is all the code.

application.html.erb

<!DOCTYPE html> <html> <head> <title>RailsVue</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> <%= stylesheet_pack_tag 'hello_vue' %> </head> <body> <div id="navbar-container"> <navbar> <navlink href="http://google.com"> Link 1 </navlink> <navlink href="http://facebook.com"> Link 2 </navlink> </navbar> </div> <%= yield %> <%= javascript_pack_tag 'hello_vue' %> </body> </html>

hello_vue.js

import Vue from 'vue/dist/vue.esm' import App from './app.vue' import Navlink from './components/navlink.vue' import Navbar from './components/navbar.vue' const navbar = new Vue({ el: "#navbar-container", components: { Navbar, Navlink } }) const app = new Vue({ el: '#hello', data: { message: "Can you say hello?" }, components: { App } })

navbar.vue

<template> <div> <nav class="navbar is-transparent"> <div class="navbar-brand"> <a class="navbar-item" href="http://bulma.io"> <img src="http://bulma.io/images/bulma-logo.png" alt="Bulma: a modern CSS framework based on Flexbox" width="112" height="28"> </a> <div class="navbar-burger burger" data-target="navMenuTransparentExample"> <span></span> <span></span> <span></span> </div> </div> <div id="navMenuTransparentExample" class="navbar-menu"> <div class="navbar-start"> <a v-for="navlink in navlinks" class="navbar-item" :href="navlink.href"> <slot></slot> </a> </div> </div> </nav> </div> </template> <script> import Navlink from './navlink.vue' export default { name: "Navbar", data: function () { return { navlinks: [] } }, created: function(){ // let children = this.$children; console.log(this.$children); // this.navlinks = this.$children; // this.navlinks = this.$children; } } </script>

navlink.vue

<template> <div class="navlink"> <slot></slot> </div> </template> <script> export default { name: "Navlink" } </script>
Categories: Software

vuejs not working on the vps

Vuejs - Sun, 2017-09-10 23:52

the initialized app ( vue init webpack my-project ) compiles successufly on the vps but when visiting "servername:8080" it renders nothing, the terminal log: DONE Compiled successfully in 3245ms

Listening at http://localhost:8080

(node:23617) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Exited with code 3 (node:23617) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

the browser console shows this error: Failed to load resource: net::ERR_CONTENT_LENGTH_MISMATCH app.js

thanks in progress :)

Categories: Software

VueJS random number gets generated only once

Vuejs - Sun, 2017-09-10 23:39

I want to make a simple VueJS app with the ability to use multiple APIs, grab an image and display it to the user. This is my first try with Vue after watching some videos of a course, so please don't hate me if I dont use a VueJS function but use pure JS.

I want that the user clicks a button, then it will request an image from an API. What works is that it picks an api randomly, but for the Flickr API I need to specify a tag (which are saved in an array, picked randomly too). But it only picks the tag once and every time I call the function again it's the same tag! Means the function only gets executed once the page is reloaded.

Why is it like this and how can I fix it? Thanks in advance.

My code so far

var vm = new Vue({ el: '#app', data() { return { // some data apis: [this.flickr(), this.desktopper()], wallpaper: '', wallpapers: [], screenWidth: window.screen.width, screenHeight: window.screen.height, } }, methods: { // The random function randomNumber(min, max) { return Math.floor(Math.random() * (max - min) + min); }, // The main function, calls an api and should get the image source requestWallpaper() { var wallpaper = this.apis[ this.randomNumber(0, this.apis.length) ]; console.log(wallpaper); }, // Flickr API request random image flickr() { // Most popular tags of all time on Flickr (tags are needed to request images)... var popularTags = ['sunset','beach','water','sky','red','flower','nature','blue','night','white','tree','green','flowers','portrait','art','light','snow','dog','sun','clouds','cat','park','winter','landscape','street','summer','sea','city','trees','yellow','lake','christmas','people','bridge','family','bird','river','pink','house','car','food','bw','old','macro','music','new','moon','orange','garden','blackandwhite']; // Grab a random tag var tag = popularTags[ this.randomNumber(0, popularTags.length) ]; return tag; }, // Desktopper.co API request random image desktopper() { return 'desktoppr'; } } });
Categories: Software

Testing Vuex action that calls external api

Vuejs - Sun, 2017-09-10 22:19

In my Vue.js project I have the following Vuex action:

import { HTTP } from '@/services/http' export const actions = { loginUser ({ commit }, params) { HTTP.post( 'v1/login', { email: params.email, password: params.password } ).then(response => { localStorage.setItem('access_token', response.data.token) commit('SET_USER', response.data) }).catch(error => { commit('SET_LOGIN_ERROR', error.response.data.error) }) } }

I'm using Mocha + Karma for unit tests. How can I test that action?

Categories: Software

Firebase does multiple calls even with if/else statement JS

Vuejs - Sun, 2017-09-10 22:04

I am building an app with Vue and also Firebase. I am new to Firebase and i've some problems with it. I try to store names + emails in the database. What I want is to check first if the email is already in the database and if not, run another function that will store the name + email. If the email is stored in the database I would like to output an alert and cancel the submit.

So the check of the email in the database is going quite well, it will output an alert, and also I am able to retrieve the data. But where the problem lays is that when I enter an email that is not in the database. When I enter a new email (and name) it will check the database and return false but then right away does another call (I dont know why, that's the problem I guess) and it will return true, and the alert of already being there, at the same time. Then it will proceed to another function to store the data because that was the output of the first call (which was false).

My JS code:

checkForm() { let app = this; if (this.name == '' || this.emailadress == '') { alert('You have to fill out the form'); } else { app.getFirebase(); } }, getFirebase() { let app = this; var ref = firebase.database().ref().child('/aanmeldingen/'); ref.on('value', function(snapshot) { const array = []; snapshot.forEach(function(childSnapshot) { var checkEmail = childSnapshot.val().email; array.push(checkEmail); }); const res = array.includes(app.emailadress); console.log(array); console.log(res); if(res) { alert('You already have entered the giveaway'); } else if (res == false) { app.store(); } }); }, store() { this.step_two = false; this.active_two = false; this.active_three = true; this.step_three = true; let app = this; firebase.database().ref('/aanmeldingen/').push({ username: app.name, email: app.emailadress, }); }

Screenshot of console (entered Jane, not in the database)

enter image description here

Categories: Software

vue.js 2 how to properly nest components

Vuejs - Sun, 2017-09-10 21:58

Can you please tell me how to properly add components to other components? The example below does not work. The child component is not displayed inside the parent.

<div id="app"> <parent> <child></child> </parent> </div> <template id='child'> <div>child component</div> </template> <template id='parent'> <div>parent component</div> </template> <script> var child = { template: '#child', data: function () { return {} } }; var parent = { template: '#parent', data: function () { return {} } }; new Vue({ el: '#app', components: { 'parent': parent, 'child': child } }) </script>

sample: https://jsfiddle.net/05gc05sk/1/

how to properly nest components?

Categories: Software

vue-router in production (serving with Go)

Vuejs - Sun, 2017-09-10 21:44

I'd like to separate client and server completely, so I created a vuejs project with vue init webpack my-project. In this project I'm using vue-router for all my routing (this includes special paths, like /user/SOMEID..

This is my routes.js file:

import App from './App.vue' export const routes = [ { path: '/', component: App.components.home }, { path: '/user/:id', component: App.components.userid }, { path: '*', component: App.components.notFound } ]

When I run the application using npm run dev everything works perfectly. I'm now ready to deploy to cloud, so I ran npm run build. Since I need to use a HTTP Server, I decided to use Go for that as well.. this is my Go file:

package main import ( "fmt" "github.com/go-chi/chi" "github.com/me/myproject/server/handler" "net/http" "strings" ) func main() { r := chi.NewRouter() distDir := "/home/me/code/go/src/github.com/me/myproject/client/dist/static" FileServer(r, "/static", http.Dir(distDir)) r.Get("/", IndexGET) http.ListenAndServe(":8080", r) } func IndexGET(w http.ResponseWriter, r *http.Request) { handler.Render.HTML(w, http.StatusOK, "index", map[string]interface{}{}) } func FileServer(r chi.Router, path string, root http.FileSystem) { if strings.ContainsAny(path, "{}*") { panic("FileServer does not permit URL parameters.") } fs := http.StripPrefix(path, http.FileServer(root)) if path != "/" && path[len(path)-1] != '/' { r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP) path += "/" } path += "*" r.Get(path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fs.ServeHTTP(w, r) })) }

I'm able to load the home page (App.components.home) where everything seem to work (the css, the images, translations, calls to and responses from the server).. but when I try to open other routes that should either result in 404 or load a user, then I just get the response 404 page not found in plaintext (not the vue notFound component it's supposed to render)..

Any ideas what I'm doing wrong and how to fix it?

Categories: Software

How to call a vue component method from another js file

Vuejs - Sun, 2017-09-10 21:41

I have a Vue v2.3.4 (quasar-framework v0.14.2) modal ComponentA working when clicking on a button in the same component. The MyModal component seems to work fine (as I can trigger it with a button). However I have code in a separate util.js file which should trigger the modal (from a 'myUtilElement'). How can I do that?

ComponentA.vue

<template> <div> <div id='lotsofstuff'></div> <myModal ref="modalTest"></myModal> </div> </template> <script> import MyModal from '../MyModal.vue' export default { name: 'componentA', components: {MyModal}, methods: { openModal: function () { this.$refs.myModal.open() }, otherMethods:...etc. }

Util.js

import ComponentA from '../ComponentA.vue' myUtilElement.addEventListener('click', triggerModal, false) function triggerModal () { ComponentA.methods.openModal() }

I now get following error in the console:

Uncaught TypeError: Cannot read property 'openModal' of undefined at HTMLElement.triggerModal
Categories: Software

setTimeout in Vue method not working

Vuejs - Sun, 2017-09-10 21:38

In my small Vue application, I'm trying to call the same method (emptyDivision) with different parameters from within another method (buttonClick). I set a 5-second timeout for the second invocation of that method, but this delay is not being recognized when I trigger these two functions by executing buttonClick.

<html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.1.1/vuex.min.js"></script> </head> <body> <div id="app"> <button v-on:click="buttonClick">Simulate Placement</button> <h1>Random Division 1</h1> <p>{{A.One}}</p> <p>{{A.Two}}</p> <h1>Random Division 2</h1> <p>{{B.One}}</P> <p>{{B.Two}}</p> </div> <script type="text/javascript"> new Vue({ 'el': '#app', 'data': { 'A': {'One': "", 'Two': "" }, 'B': {'One': "", 'Two': "" }, 'Division1': ["Steelers", "Ravens"], 'Division2': ["Broncos", "Raiders"], }, 'methods': { 'emptyDivision': function(division){ this.A[division] = this.popTeam(division)[0]; this.B[division] = this.popTeam(division)[0]; }, 'popTeam': function(division) { if (division === "One"){ return this.Division1.splice(Math.floor(Math.random()*this.Division1.length), 1); } return this.Division2.splice(Math.floor(Math.random()*this.Division2.length), 1); }, 'buttonClick': function() { setTimeout(function() {console.log("This appears after 3 seconds")}, 3000); setTimeout(this.emptyDivision("One"), 5000); /*Teams in division one ("Steelers" and "Ravens") should be propagated to the DOM after 5 seconds, but it's being evaluated at the same time as the invocation to this.emptyDivision("Two") */ this.emptyDivision("Two"); /* I expect ("Broncos" and "Raiders" to be rendered to the DOM first due to the timeout, but this is not happening*/ } } }) </script> </body> </html>

After inspecting the console, the three-second timeout log statement is evaluated and produces the expected behavior, but the five-second timeout to emptyDivision("one") does not appear to be working, as detailed by the comments I left in the above code.

Categories: Software

Slide Reverse Transitions, Vue Js

Vuejs - Sun, 2017-09-10 20:39

I'm developing a single page application / mobile app, with VUE JS, I want a slide effect when changing the pages, and I can do it like this:

transition name="slide" router-view transition transition

But I wanted the reverse effect of the slide when the user returns the page, in other words, when the user opens a new page, the page will come from the right, when they go back, the page will come from the left. There is a plugin for vue router, called vue-router-transition https://www.npmjs.com/package/vue-router-transition But it does not work, it is out of date, it only works with very old versions of the vue

Also there is a tutorial on how to make dynamic transitions, but only works when it is parents routes, ex: site.com/rota1/rota2/rota3 Which is not my case https://router.vuejs.org/en/advanced/transitions. html

I thought of the following logic in the before.each.router, set the transition class, (slide-left or slide-right) depending on whether the user clicked on a go back button, the problem is that I do not know how to apply this logic in code, I would have to pass the value of a variable that is in main.js to the app.vue and I do not know how to do this ...

If anyone can help me, thank you!

Categories: Software

vue: Wrong type check for prop

Vuejs - Sun, 2017-09-10 19:20

My component has in data section:

photos: ['images\1.jpg','images\2.jpg']

In template (pug) :

... v-carousel v-carousel-item(v-for='(item,i) in photos',:key='i', :src='item')

I got 2 warnings:

[Vue warn]: Invalid prop: type check failed for prop "src". Expected String, got Number. found in --->

If

:src='item'

change to

:src='item.toString()'

there are no warnings.

Is it Vue or Vuetify or my error?

Categories: Software

Vue js Cli app running in another computer

Vuejs - Sun, 2017-09-10 18:55

I would like to share my Vue js application project which is in my repository with a friend. So I used vue-cli, npm/yarn and webpack to develope. I would like to know if he needs to install also cli to run the app on his computer, or just npm install and npm run? thanks

Categories: Software

How to separate opening and closing tag by conditional template in vue without getting compiling error?

Vuejs - Sun, 2017-09-10 17:19

I am trying to do some conditional templating where I have to separated the opening and closing tags of some elements. But can't get it to work until they are in the same conditional template tag. As soon as I put the opening tag to one conditional template and the closing tag to another conditional template I get an error. For example:

<template> <div> <template v-if="show"> <ul> <li> one </li> </template> // OTHER CONDITIONAL STUFF IN BETWEEN <template v-if="show"> <li> two </li> </ul> </template> </div> </template> <script> export default { data() { return { show: false } } } </script>

Here I get an error because the opening <ul> tag and closing </ul> tag are in discrete <template v-if=".."> tags. I get this error:

(Emitted value instead of an instance of Error) Error compiling template: <div> <template v-if="show"> <ul> <li> one </li> </template> <template v-if="show"> <li> two </li> </ul> </template> </div> - tag <ul> has no matching end tag.

How can I separate any starting and ending tags inside conditional template tags without breaking the code?

Categories: Software

Vue creating a plugin

Vuejs - Sun, 2017-09-10 17:08

I feel a bit like I'm missing something very simple, but I've been trying different stuff out and searching all over the place and can't figure out how to use a method from a custom plugin in my Vue application.

In 'vuePlugin.js' I have something like:

const myPlugin = {}; myPlugin.install = function(Vue, options){ Vue.myMethod = function(){ console.log("It worked!"); } }

In my main.js I have:

import myPlugin from './js/vuePlugin.js' Vue.use(myPlugin);

Then in my App.vue I have:

export default { name: 'app', props: {}, data () { return{ someData: 'data' } }, beforeCreate: function(){ myMethod(); } }

With this I get an error that "myMethod is not defined".

I've tried saying:

var foo = myPlugin(); console.log(foo);

In my console I get an object called "install" with arguments: "Exception: TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context. at Function.remoteFunction"

All of the documentation seems to just show how to create the plugin and "use" it, but not actually how to access anything in it. What am I missing here?

Categories: Software

Vue.js focus input inside different component on keypress

Vuejs - Sun, 2017-09-10 16:32

I have a <table> with rows containing form inputs.

I want to simulate a spreadsheet behavior, meaning that when you press the key UP or DOWN the focus should change to the next/previous row's input.

The way I'm building this is attaching an event handler in the input like this:

<td><input v-model="period.end" v-on:keydown="moveIfCursorUpOrDown"></td>

The question is how to focus an input inside a different component inside moveIfCursorUpOrDown method.

I know of this.$refs.nameOfInput.focus(), which works to focus the inputs belonging to the component itself, but I don't know how to use this to focus the input inside a different component.

Categories: Software

vue js computed method

Vuejs - Sun, 2017-09-10 16:29

I'm pretty new with Vue and Js and I'm a bit confused with computed methods. So as follows I create a props to share data from the parent component. Everything works but when the sumTotal method its executed as a default value its displaying Nan on the {{sumTotal}}. How I can fix the sumTotal method?

<v-layout row v-for="color in colors" :key="color.id"> <v-layout > <v-flex > <v-checkbox class="text-xs-right" name="checkbox" v-bind:label="`${color.name}`" v-model="color.checked" light></v-checkbox> </v-flex> </v-layout> <v-layout column> <v-flex > <v-subheader>{{color.price}} €</v-subheader> </v-flex> </v-layout> <v-subheader> {{sumTotal}} €</v-subheader> </v-layout> <script> export default { props: ['myProp'], data: () => ({ colors: [{ id: 1, name: "White", price: 5, }, { id: 2, name: "Green", price: 4, }, { id: 3, name: "Blue", price: 3, }, { id: 4, name: "Red", price: 2, }, { id: 5, name: "Purple", price: 1, }, { id: 6, name: "Yellow", price: 0, }], }), computed: { total: function() { var total = 0; for (var i = 0; i < this.colors.length; i++) { if (this.colors[i].checked) { total += this.colors[i].price; } } return total; }, sumTotal: function() { var myProp = 0; return this.total + this.myProp; } }, } </script>
Categories: Software

Javascript: indexOf always returns -1, but not for all arrays

Vuejs - Sun, 2017-09-10 15:16

I'm using Vue.js. I have two arrays, checkedTracks and checkedAlbums. Both are created and populated in the same way (see initialiseAlbums) and both contain elements of type string.

The updateArray method takes an array and array element as parameters. If the element is in the array, it is removed. If it is not in the array, it is added. When I call the method updateArray and pass the checkedTracks array, it performs as expected. However when I pass checkedAlbums, the index is always -1.

While debugging the method with checkedAlbums I noticed a few things.

  • The data types of the element being passed in and the array elements are the same
  • The array contains data, however array[0] returns undefined
  • Manually passing the ID string to the indexOf function still returns 0, despite being identical

Can anyone provide some insight as to what is going on here? Thanks in advance.

<script> import Album from './Album' import EventBus from '../event-bus' import Sort from './Sort' import Modal from './Modal' export default { components: { 'album': Album, 'sort': Sort, 'modal': Modal }, props: { results: [] }, data () { return { allAlbums: [], checkedTracks: [], checkedAlbums: [], artist: {}, createPlaylistMessage: '', showModal: false, published: false, playlistUrl: '' } }, mounted () { EventBus.$on('albums', this.initialiseAlbums) EventBus.$on('artist', this.initialiseArtist) }, computed: { resultsPresent: function () { return this.allAlbums.length > 0 } }, methods: { initialiseAlbums: function (allAlbums) { let self = this self.allAlbums = [] self.checkedAlbums = [] self.checkedTracks = [] allAlbums.forEach(function (album) { if (album.tracks.items !== null) { self.allAlbums.push(album) self.checkedAlbums.push(album.id) album.tracks.items.forEach(function (track) { self.checkedTracks.push(track.id) }) } }) }, initialiseArtist: function (artist) { this.artist = artist }, toggleSingleAlbum: function (albumId) { this.updateArray(this.checkedAlbums, albumId) }, updateTrack: function (trackId) { this.updateArray(this.checkedTracks, trackId) }, updateArray: function (array, element) { let index = array.indexOf(element) if (index > -1) { array.splice(index, 1) } else { array.push(element) } }, updateSort: function (albums) { this.allAlbums = albums }, publishPlaylist: function () { this.published = false let playlist = {} playlist.tracks = this.checkedTracks playlist.name = this.artist.name this.$http.post('/publish', playlist).then(function (response) { if (response.status === 201) { this.published = true this.playlistUrl = response.data this.createPlaylistMessage = 'Playlist created successfully' } else { this.createPlaylistMessage = 'Playlist could not be created' } this.showModal = true }).catch(function (error) { console.log(error) }) } } } </script>
Categories: Software

How to start a v-for loop at a specific index.

Vuejs - Sun, 2017-09-10 14:30

How to start a v-for loop at a specific index. example: A array given array = [a,b,c,d,e,f]; I want use v-for loop which will start looping from 3rd element. Thank you :)

Categories: Software

How to stop router from a component?

Vuejs - Sun, 2017-09-10 13:54

There is a component
It takes some action and a person should not leave without having saving
There is method beforeDestroy()
This works fine, but I do not understand how to stop transition.
Rather, the link changes, but the component has not yet deleted.

Categories: Software

How to apply Vue.js scoped styles to components loaded via view-router?

Vuejs - Sun, 2017-09-10 13:09

How can I apply Vue.js scoped styles to components loaded via <view-router>.

Here is my code:

<template> <div id="admin"> <router-view></router-view> </div> </template> <style lang="scss" scoped> #admin { .actions { display: none; span { cursor: pointer; } } } </style>

When I visit the /posts a component named Posts will be loaded, inside this component I have a

<div class="actions"> some content </div>

The problem is that the style defined in #admin is not applied to .action element. When not scoped, this works fine. The problem come when the #admin component styling is scoped.

Is there any way to do that while keeping the .actions style inside the admin component scoped style tag?

Categories: Software

Pages