Software
framework7 issue with a accordion
i am using framework7 last version , and my app hierarchy is like that :
vue router-view , vue children are loaded within router-view , one of those children is the root of framework7 app , when i navigate between "the root of framework7 which is a component" and any other component , the accordion animation start to stuck and act unexpectedly but it works good before navigation done .
i try to reset everything here with in the vue component which acts as root
export default { data() { return { appIsRdy: false } }, mounted() { this.$store.state.f7.f7Obj = new Framework7({ root: '.f7root' }); this.$store.state.f7.$$ = Dom7; this.$store.state.f7.mView = this.$store.state.f7.f7Obj.addView('.view-main', { domCache: true }); this.appIsRdy = true; }, components: { MainPage, RedditPage }, beforeDestroy() { this.$store.state.f7.f7Obj = null; this.$store.state.f7.$$ = null; this.$store.state.f7.mView = null; this.appIsRdy = false; } }How connect with server on client side with Vue.js, Socket.io, Arduino?
I have a problem with connection server by client application. I want to connect with my arduino board and control by client side wriiten in vue.js.
I have a server who run on node.js, and run good.
const http = require('http'); const socketIo = require('socket.io'); const port = process.env.PORT || 5000; const server = http.createServer().listen(port, () => { }); const five = require('johnny-five'); const board = new five.Board(); const pin = { 13: { led: { on: () => console.log('on'), off: () => console.log('off'), }, }, }; const io = socketIo(server); board.on('ready', () => { const led = new five.Led(13); led.off(); pin[13].led = led; }); io.sockets.on('connection', (socket) => { socket.on('message', (channel, message) => { if (channel === 'on') pin[message].led.on(); if (channel === 'off') pin[message].led.blink(500); }); });but i have a problem with client-side. This is my code, and i don't know what can i do now.
<template> <router-view> </router-view> </template> <script> import Vue from 'vue'; import VueRouter from 'vue-router/dist/vue-router'; import LoginRoutes from 'features/login/login.routes'; import FoobarRoutes from 'features/foobar/foobar.routes'; import 'common/components'; import Jquery from 'jquery'; import BootstrapCSS from 'bootstrap/dist/css/bootstrap.css'; import Bootstrap from 'bootstrap'; Vue.use(VueRouter); io = require("socket.io/lib/socket"); var socket = io.connect("http://localhost:5000"); const routes = [ { path: '/', redirect() { return '/login'; }, }, ...LoginRoutes, ...FoobarRoutes, ]; const router = new VueRouter({ routes, }); export default { router, }; </script>and this is my view :
<template> <div> <h1>TURN ON/OFF LED</h1> <button class="btn btn-danger" @click='on'>13: ON</button> <br><br> <button @click='off'>13: OFF</button> </div> </template> <script> export default { name: 'login-view', methods: { on: function() { socket.send('on', 13); // this.$socket.emit('on', 13); }, off: function() { socket.send('off', 13); }, }, }; </script> <style> </style>variable inside watch not reactive vuejs
I am watching an array and if some conditions met I want to disable / modify other elements but no luck so far, as the variable already_answered is not reactive.
<input :disabled="already_answered" type="text" /> data: function() { return { already_answered: false, somearr: [], }; }, watch: { somearr() { for (var i = 0; i < this.somearr.length; i++) { if (this.somearr[i]["id"] == 5) { this.already_answered = true break; } } }, },How insert one-to-many
There is a database with two tables (recipe, flavor). Between them one-to-many relationships one recipe is a lot of flavors. I add data through the put vue method
saverecipe: function(){ this.$http.put('/recipe/new', this.newrecipe).then(function (data) { console.log(this.newrecipe) }) }Google Chrome data example with one flavor
handler
func PutRecipe(db *sql.DB) echo.HandlerFunc { return func(c echo.Context) error { var recipe models.Recipe c.Bind(&recipe) id, err := models.PutRecipe(db, recipe.RECIPENAME, recipe.BOTTLEID, recipe.BOTTLESIZE, recipe.PG, recipe.VG, recipe.NICOTINE, recipe.DATE, recipe.NOTE, recipe.FLAVORID, recipe.NAME, recipe.DROPS, recipe.RECIPEID) if err == nil { return c.JSON(http.StatusCreated, H{ "created": id, }) } else { log.Fatal(err) return err } } }model
func PutRecipe(db *sql.DB, recipename string, bottleID int, bottlesize int, pg int, vg int, nicotine int, date string, note string, flavorid int, name string, drops int, recipeid int) (int64, error) { sql := `INSERT INTO recipe(recipename, bottleID, bottlesize, pg, vg, nicotine, date, note, flavorid) VALUES(?,?,?,?,?,?,?,?,?,?,?,?); INSERT INTO flavor(name, drops, recipeid) VALUES(?,?,?)` stmt, err := db.Prepare(sql) if err != nil { log.Fatal(err) } defer stmt.Close() result, err2 := stmt.Exec(recipename, bottleID, bottlesize, pg, vg, nicotine, date, note, flavorid, name, drops, recipeid) if err2 != nil { log.Fatal(err2) } return result.LastInsertId() }Data must be written in two tables. One is a recipe. One - flavor. How can I do that? If you need I can lay out all the code on the github
Lazy loading images in Vue/Laravel
I am trying to use jQuery Lazy Loading in my Laravel/Vue project but I am struggling to get an image to appear in my Vue component. I have the following img block which I thought would work:
<img v-if="vehicle.photo_path != null" :data-original="'/storage/vehicles/' + vehicle.photo_path" class="lazy" height="180" width="150"/>I did find this other question on here - Static image src in Vue.js template - however when I try that method I get this: Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead.
So I switched back to the v-bind method but all I am getting is a white box with a grey border - no image. If I v-bind on the src attribute however I can see the image correctly.
I know I have implemented the Lazy Loading plugin correctly as I can successfully call it elsewhere on my site (such as on a blade view), but I'm not sure where I am going wrong. Thank you.
Property or method "orgs" is not defined on the instance but referenced
I am using vue2 and I am trying to fetch an api and render the contents in my page, this is all done in my Orgs.vue file and here is the code:
<template lang="html"> <div class=""> {{ orgs | json }} </div> </template> <script> export default { data: { orgs: false }, created() { request = axios({ url: 'https://....', method: 'GET', }) .then(function(response) { this.orgs = response; }) .catch(function(error) { console.log('error getting orgs::', error); }); } }; </script> <style lang="css"> </style>However everytime I run the page I get this error:
Property or method "orgs" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. found in Orgs.vue
I tried to change
data: { orgs: false },to
data() { return {orgs: false} },but the error is still there
Vue.js doen't render components
I am using Vue.js and i want to try to render components but it isn't working
main.js:
import Vue from 'vue'; import 'bulma'; import Navbar from './Navbar.vue'; Vue.component('navbar', Navbar); const MyC = Vue.component('myc', { template: '<h1>Are you working?</h1>', }); const root = new Vue({ el: '#app', components: { Navbar, MyC, }, });index.html
<body> <div id="app"> <navbar></navbar> <myc></myc> </div> <script src="dist/build.js"></script> <!-- Webpack endpoint --> </body>Navbar.vue
<template> <h1>HELLO FROM NAVBAR</h1> </template> <script> // Some logic here export default { name: 'navbar', }; </script>I coded as written in guide but neither of the ways to render a component is working
I just have blank page
I am using webpack+vue-loader
Vue in Laravel project doesn't appear
I'm starting to work with laravel and I try to use Vue. So on my resources/assets/js/app.js I have
Vue.component('example', require('./components/Example.vue')); const app = new Vue({ el: '#app' });So my Example.vue is basicly what it's given with laravel. And in my welcome.blad I have
@extends('layouts.app') @section('content') <example> </example> @endsection <script src="{{ elixir('js/app.js') }}"></script>in my package.json I have :
"devDependencies": { "vue": "^2.1.10", "vue-resource": "^1.0.3" }But Nothing appear in my welcome page. I ran npm install npm run dev And change several things in my script, don't remember all but tried a lot of things and can't make it work
deleting child component removes that component and all child components created after it
I've run into a problem when I delete a component any component created after it deleted and then recreated. Component in question gets deleted and child component created after it get deleted and then recreated.
Is there a reason why this is happening?
here is a video of it: maxniko.tinytake.com/sf/MTg3NTc2M182MDIyMzI5
Here is fiddle: jsfiddle.net/xk5yL3h8
fiddle code:
Vue.component('column-component', { props: ["columnData", "uniqueId"], mounted: function() { console.log('mounting column: ' + this.uniqueId) }, beforeDestroy: function() { console.log('removing: ' + this.uniqueId) }, template: ` <div style="float: left; padding: 10px; margin-right: 10px; border: 1px solid black;">aaa</div>` }) Vue.component('row-component', { props: ["rowData", "uniqueId"], data: function data() { return { columns: [], columnCount: 0 } }, mounted: function() { console.log('mounting row: ' + this.uniqueId) }, methods: { addColumn() { console.log var column = new Object() column.uniqueId = this.uniqueId +'.col.'+ this.columnCount this.columns.push(column) this.columnCount = this.columnCount + 1 } }, beforeDestroy: function() { console.log('removing: ' + this.uniqueId) }, template: ` <div> <div style="margin: 10px; padding: 20px; background: rgba(0,0,0, 0.5);"> row component: {{rowData.text}} <div class="column" v-for="(column, index) in columns"> <column-component column-data="abc" :uniqueId="column.uniqueId"></column-component> </div> <div style="clear: both;"></div> <div style="margin-top: 35px;"> <button @click="addColumn()">add column</button> </div> </div> </div>` }) new Vue({ el: '#app', template: ` <div> <div v-for="(row, index) in rows"> <row-component :uniqueId="row.uniqueId" :row-data="row" :key="row.uniqueId"></row-component> <button @click="deleteThisRow(index)">remove row</button> </div> <button @click="addRow()">add</button> </div> `, data: { rows: [], rowCount: 0 }, mounted: function() { this.addRow() this.addRow() this.addRow() }, methods: { addRow() { var row = new Object() row.uniqueId = 'row-' + this.rowCount row.text = 'row-'+(this.rows.length) this.rows.push(row) this.rowCount = this.rowCount + 1 }, deleteThisRow: function(index) { this.rows.splice(index, 1) console.log(this.rows) } } })Vue.js: Assigning computed result to data property at created or mounted?
Is it possible to do the following?
export default { props: ['parentArray'], data () { return { computedArray: null } }, computed: { computedResult: function () { var flags = [] var output = [] var l = this.parentArray.length var i for (i = 0; i < l; i++) { if (flags[this.parentArray[i].myitem]) continue flags[this.parentArray[i].myitem] = true var firstfilter = this.parentArray[i].myitem.replace('something', '') output.push(firstfilter) } return output } }, mounted () { this.computedArray = this.computedResult }When I try, the structure of my array makes it to the data element, but none of the data (at least not in the vue dev-tools. The computed array properly shows up in computed)
Perform edition with vuejs modal
The title is just a simple intro to what the real problem is, basicly i have a dashboard with a lot of elements (example: table, paragraph, heading) this elements are respective to a construction of a docx document.
Everytime i click one of these elements i open a new modal, where i can change some parameters in order to create the element, for example with paragraph i can change his alignment, color and text.
When i click to add this element it is added to a section in my page as a block and i should be able to change the properties of each block by clicking above the block.
I want to open a new modal(something like the modal when i open in the dashboard, with the difference instead of adding, to edit).
My problem is that i don't know what is the best way to do this without having messy spaghety code.
At the moment i am building it this way:
i have the dashboard component that is like this:
<template> <div class="navbar navbar-custom navbar-fixed-left navSize"> <form class="navbar-form margin-above" role="search"> <div class="input-group add-on"> <input class="form-control" placeholder="Search" name="srch-term" id="srch-term" type="text"> </div> </form> <h4 class="text-center">Doc Sections</h4> <div @click="changeView('appTable')" class="card card-color"> <div class="card-block"> <h4 class="card-title text-center">Table</h4> </div> </div> <div @click="changeView('appParagraph')" class="card card-color"> <div class="card-block"> <h4 class="card-title text-center">Paragraph</h4> </div> </div> <div @click="changeView('appImage')" class="card card-color"> <div class="card-block"> <h4 class="card-title text-center">Image</h4> </div> </div> <div @click="changeView('appBulletList')" class="card card-color"> <div class="card-block"> <h4 class="card-title text-center">Bullet List</h4> </div> </div> <div @click="changeView('appHeading')" class="card card-color"> <div class="card-block"> <h4 class="card-title text-center">Heading</h4> </div> </div> <div @click="changeView('appBreak')" class="card card-color"> <div class="card-block"> <h4 class="card-title text-center">Break</h4> </div> </div> </div> </template> <script> export default { data() { return { text: "", fontSize: 14, key: "Paragraph", paragraph: {}, } }, methods: { addParagraph() { this.$set(this.paragraph, 'key', this.key); this.$set(this.paragraph, 'text', this.text); this.$set(this.paragraph, 'fontSize', this.fontSize); this.$store.commit("appendToDocument", this.paragraph) }, changeView: function (view) { this.$store.commit("changeCurrentView", view); this.show(); }, show() { this.$modal.show('modalSection'); }, hide() { this.$modal.hide('modalSection'); }, hey() { console.log("HEY"); } }, } </script>the change view sends to vuex the new component that should render the modal, i have this at vuex store:
currentView: 'appTable', changeCurrentView: (state, view) => { state.currentView = view; },in my create file template is the place where i render the component that i click, like this:
<modal name="modalSection"> <component :is="getView"> </component> </modal> computed:{ getView(){ return this.$store.getters.getCurrentView; } },again, i access vuex for the currentView clicked and change the component rendered. In this page i also load the components to be displayed but i think the important part about how it works is already showed, each component has its own properties inside, for example Table is 1 component with his properties inside it, like(number of rows, columns).
Do i need to pass all this properties from all my components to vuex? so i can edit them in other component. Or is there a better way?
Thank you guys
Import javascript file after component is mounted
i am building spa using vuejs as the frontend and laravel as the backend, and i purcased some admin bootstrap template named limitless (very cool admin template by the way).
But there is the problem with this template that in the main javascript file (app.js in admin directory) there is this line
// Calculate min height function containerHeight() { var availableHeight = $(window).height() - $('.page-container').offset().top - $('.navbar-fixed-bottom').outerHeight(); $('.page-container').attr('style', 'min-height:' + availableHeight + 'px'); } // Initialize containerHeight();and because i am using spa vuejs so i only include all js file in my admin.blade.php file like this
<!DOCTYPE Html> <Html lang="{{ config('app.locale') }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'> <meta name="description" content=""> <meta name="author" content=""> <script> window.Laravel = <?php echo json_encode([ 'csrfToken' => csrf_token(), ]); ?> </script> <title>SIMO</title> <meta name="csrf-token" content="{{ csrf_token() }}" /> <!-- icon--> <link rel="icon" href="{{asset('images/logo.png')}}" sizes="16x16"> <link rel="icon" href="{{asset('images/logo.png')}}" sizes="32x32"> <link rel="apple-touch-icon" href="{{asset('images/logo.png')}}"/> <link rel="apple-touch-icon" href="{{asset('images/logo.png')}}" sizes="76x76" /> <link rel="apple-touch-icon" href="{{asset('images/logo.png')}}" sizes="120x120" /> <link rel="apple-touch-icon" href="{{asset('images/logo.png')}}" sizes="152x152" /> <link rel="apple-touch-icon" href="{{asset('images/logo.png')}}" sizes="180x180" /> <!-- Bootstrap Core CSS --> <link href="https://fonts.googleapis.com/css?family=Roboto:400,300,100,500,700,900" rel="stylesheet" type="text/css"> <link rel="stylesheet" type="text/css" href="{{asset('css/admin/icons/icomoon/styles.css')}}" > {{-- <link rel="stylesheet" type="text/css" href="{{asset('css/admin/icons/fontawesome/styles.min.css')}}" > --}} <link rel="stylesheet" type="text/css" href="{{asset('css/admin/bootstrap.css')}}" > <link rel="stylesheet" type="text/css" href="{{asset('css/admin/core.css')}}" > <link rel="stylesheet" type="text/css" href="{{asset('css/admin/components.css')}}" > <link rel="stylesheet" type="text/css" href="{{asset('css/admin/colors.css')}}" > @yield('css') <!-- Html5 Shim and Respond.js IE8 support of Html5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/Html5shiv/3.7.0/Html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <div id="app"></div> <script type="text/javascript" src="{{ URL::asset('js/app.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/plugins/loaders/pace.min.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/libraries/jquery.min.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/libraries/bootstrap.min.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/plugins/loaders/blockui.min.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/plugins/ui/nicescroll.min.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/plugins/ui/drilldown.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/plugins/buttons/hover_dropdown.min.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/plugins/forms/selects/bootstrap_select.min.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/plugins/ui/ripple.min.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/admin/app.js') }}"></script> </body> </Html>and after inspecting the code i found out that it need div with class page-container and this div is located after header part so in my index.vue page i put it like this
<template> <div> <div class="page-header"> //here is header </div> <div class="page-container"> //content </div> </div> </template>so it will throw
Uncaught TypeError: Cannot read property 'top' of undefinedbecause when the page loaded it don't find any div with page-container class, since it not there yet.
And from what i read in vuejs documentation about lifecycle, this entire admin/app.js code should be run in mounted() or created() vuejs function. But from the example in documentation and around the internet it just used for run some javascript function but not include entire javascript file so it will be executed in there....
so my question is how to solve this? or for more simple way, how to add external css file and javascript file in component(this index.vue is called component right?) some people tell me to make it module and import it but i have no idea how to do that....
from what i know is i can download javascript plugin like moment from npm and it magically can be called within vue with import moment from moment but how about the local javascript files?
zoom issue in dagre-d3 when use with vuejs2 with watch mode
I am using d3-dagre to render the data. Initially i can render the data without any problem. When i try to update the same view in watch mode, it is updating the data but still some error is thrown in the console for "g" attribute transformation. Whenever i try to rewrite the SVG elements i am removing the "g" element inside the "svg" tag. I am trying this in vuejs2 ui library.
watch: { workflowDetails: function (changes) { console.log('Update component ==> ' + changes) this.workflowName = changes.label this.workflowDetails = changes this.metricGraph = false this.drawDAGView() } }, mounted () { this.drawDAGView() }, methods: { getJobid: function (nodeId) { console.log('Function to get graph api' + nodeId) this.metricGraph = true }, drawDAGView: function (isUpdate) { /* eslint-disable */ d3.selectAll('svg > g').remove() // Create a new directed graph var g = new dagreD3.graphlib.Graph().setGraph({}) var DagNodes = this.workflowDetails.nodes var fillColor // Add states to the graph, set labels, and style Object.keys(DagNodes).forEach(function(key) { console.log("Nodes - "+ DagNodes[key].name) var value = DagNodes[key] value.label = DagNodes[key].name + " (" + DagNodes[key].exec_time + ")" value.rx = value.ry = 5 g.setNode(DagNodes[key].name, value) }) var DagEdges = this.workflowDetails.edges; // Add states to the graph, set labels, and style Object.keys(DagEdges).forEach(function(key) { g.setEdge(DagEdges[key].startEdge, DagEdges[key].endEdge, { label: ""} ) }) // Create the renderer var render = new dagreD3.render() // Set up an SVG group so that we can translate the final graph. var svg = d3.select("svg"), inner = svg.append("g") // Set up zoom support var zoom = d3.behavior.zoom().on("zoom", function() { inner.attr("transform", "translate(" + d3.event.translate + ")" + "scale(" + d3.event.scale + ")") }) svg.call(zoom) // Simple function to style the tooltip for the given node. var styleTooltip = function(name, description) { return "<p class='name'>" + name + "</p><p class='description'>" + description + "</p>" } // Run the renderer. This is what draws the final graph. render(inner, g) inner.selectAll("g.node") .attr("title", function(v) { return styleTooltip(v, "Execution Time: "+g.node(v).label + " <br /> Description: "+g.node(v).label) }) //.each(function(v) { $(this).tipsy({ gravity: "w", opacity: 1, html: true }) }) var self = this inner.selectAll("g.node") .on("click", function(v) { console.log("Nodes --> "+ v + " -- "+ g.node(v).node_id) // whatever //window.location = "../dag/"+g.node(v).job_id self.nodeId = g.node(v).node_id console.log("Node id -- "+ self.nodeId) self.getJobid(self.nodeId) }) // Center the graph var initialScale = 1.2 zoom .translate([(svg.attr("width") - g.graph().width * initialScale) / 50, 20]) .scale(initialScale) .event(svg) svg.attr('height', g.graph().height * initialScale + 40) svg.attr('width', "100%") }Error - Due to this below error newly loaded data not able to zoom
Error: <g> attribute transform: Expected number, "translate(NaN,20)Include bootstrap features into a custom vuejs component
I'm asked to add a new html page to a vuejs project. This page is already fully developed and is based on jquery and some twitter-bootstrap features.
I've created a new component.
newPage.vue
<template> <div id="my-new-page"> ... </div> </template> <style src="path/to/_bootstrap.scss" lang="scss" scoped></style> <style src="path/to/font-awesome.scss" lang="scss" scoped></style> <style src="path/to/animate.css" scoped></style> <style src="path/to/custom/css.css" scoped></style> <script src="path/to/custom/js.js"></script>js.js
import jQuery from 'jquery'; // Same error even with window.$ = window.jQuery = jQuery; import collapse from 'path/to/bootstrap/feature/collapse.js"; export default { created() { runjQuery(jQuery); }, }; function runjQuery($) { // here is how I thought integrate the jquery script of the new html page $(function () { .... $('#navbar').collapse('hide'); }); }But this obviously does not work because collapse.js cannot access jQuery and I get this error
Uncaught ReferenceError: jQuery is not definedHow do I fix this problem?
Given that I don't want (if possible) to add bootstrap and jquery globally to my project because this will surely breaks here and there in my other components?
Update array element in Vuejs
I'm having a data set which is by default have following:
summaries: [{client:'', type: '', mention: '', action: '', comment: '', button: true}],I've a button which adds the same data set into summaries data:
addSummary() { this.summaryHeaders = true; this.summaries.push({ client: '', type: '', mention: '', action: '', comment:'', button: true }) },Now I'm having other button, while being clicked I want to update button attribute as false of that particular data set. How can I achieve this?
How to populate store in vuex before component renders
I am using vuex to save a tree structure in the state property.
The data is fetched with an ajax call.
The problem is that the page manages to render before the variable I have in the state property manages to populate.
i.e
// sth.ts file state: { map: {} }, ... actions: { axios.get(...).then(... populate map ...).catch(...) } // sthelse.vue file <template> <div> <h1>Tree structure</h1> <ul > <item v-for="child in map[root]" :key="child.id" :name="child.name" :children="child.Children"> </item> </ul> </div> </template>I have googled but I haven't found something that works. Has anybody dealt with a similar problem?
Is there a way it can be done?
deleting component from array, vuejs removes wrong component
I need to be able to delete specific component from the array. I do this with splice and although that component definition is removed from array, vuejs removes wrong component. It allways removes the last added component.
Here is a fiddle that provides demonstration of that:
https://jsfiddle.net/wjjonm8n/
and here is video to show what is happening:
https://maxniko.tinytake.com/sf/MTg3NTI5NF82MDIxNDAx
here is some code:
Vue.component('row-component', { props: ["rowData", "uniqueId"], mounted: function() { console.log('mounting: ' + this.uniqueId) }, beforeDestroy: function() { console.log('removing: ' + this.uniqueId) }, template: ` <div> row component: {{rowData}} <button @click="$emit('delete-row')">Delete</button> </div>` }) new Vue({ el: '#app', template: ` <div> <row-component v-for="(row, index) in rows" :row-data="row" :uniqueId="index" v-on:delete-row="deleteThisRow(index)"></row-component> <button @click="add()">add</button> </div> `, data: { rows: ["line1", "line2", "line3", "line4", "line5"], }, methods: { add() { this.rows.push('line'+(this.rows.length+1)) }, deleteThisRow: function(index) { this.rows.splice(index, 1) console.log(this.rows) } } })this function tells me what vuejs really removes:
beforeDestroy: function() { console.log('removing: ' + this.uniqueId) }it removes last added component if you look at what that console.log function prints. This is problem because on mount of each component I create listener for just that component:
this.$bus.$on('column-'+this.uniqueId+'-add-block', this.handlerMethod)when vue removes last component, this event listener no longer works.
How can I solve this?
In my own application this is how I create child component:
let column = new Object() column.uniqueId = this._uid+'-column-' + this.addedColumnCount column.text = '1/2' this.columnList.push(column) this.addedColumnCount = this.addedColumnCount + 1notice how I create uniqueId for component when I add it:
column.uniqueId = this._uid+'-column-' + this.addedColumnCountwhen I try to delete a component it allways reports to me that the component with last added uniqueId is being removed.
beforeDestroy: function() { this.$bus.$off('column-'+this.uniqueId+'-add-block', this.handlerMethod) console.log('removing: ' + this.uniqueId) },How to use variables of data function on VueJS?
I have a stupid problem with VueJS. I'm new with VueJS. I want to access and change variables of data function. However I couldn't do it.
Here is my code:
data: function(){ return { item: 69, file: 0 }; }, methods: { toggle: (elementId = 0, type = 'item') => { console.log('element ID: ' + elementId); console.log('type: ' + type); console.log('item: ' + this.item); switch (type) { case 'item': break; case 'file': break; } } }For loop and strange Vue behaviour
I'm working on a project where I want to add some more input fields when clicking on a button. So I tried jQuery.append but then there was a problem with v-model not being detected. So I tried to achieve the same thing using Vue if-statement and I figured out it could be done much simpler by just adding objects to the variable deciding how many input fields listed in the first place.
But then I noticed something strange and I would like to know if this is by accident or if it's meant to work this way.
So first of all - this is the html:
<div id="app-edit" class="form-group"> <template v-if="plate.props.products !== undefined"> <div class="form-group form-row" v-for="(extra, index) in plate.props.products"> <div class="col"> <label for="productExtrasNobb0" v-if="index == 0">NOBB number</label> <input type="text" class="form-control" v-bind:id="'productExtrasNobb' + index" v-model="plate.props.products[index].nobb"> </div> <div class="col"> <label for="productExtrasAmount0" v-if="index == 0">Amount</label> <input type="text" class="form-control" v-bind:id="'productExtrasNumber' + index" v-model="plate.props.products[index].number"> </div> <div class="col-auto d-flex align-items-end"> <button type="button" class="btn btn-danger"><i class="fa fa-minus"></i></button> </div> </div> <template v-if="extraAddons > 0"></template> <button type="button" class="btn btn-info" @click="addExtra(plate.props.products.length)"><i class="fa fa-plus mr-2"></i>Add</button> </template> <template v-else> <button type="button" class="btn btn-info" @click="addExtra(plate.props.products.length)"><i class="fa fa-plus mr-2"></i>Add</button> </template> </div>And this is the relevant Vue JS:
var app = new Vue({ el: '#app-edit', data: { extraAddons: 0, plate: { props: { products: [], } } }, methods: { addExtra: function(number) { vm = this; vm.plate.props.products[number] = {nobb:'',number:''}; vm.extraAddons++; } } });The thing is this is working fine. When I press the button to add an extra block it is inserted. But if I remove
<template v-if="extraAddons > 0"></template>it's not working. Why is that relevant at all? It doesn't matter what tag I use - it could be p instead of template and still the same result but it seems like the v-if statement is triggering some sort of rendering?
Could anyone please explain so I can understand better why this is happening?
Vue Autocomplete component with slot instead of input
I have created custom autocomplete component which works as material input, but on focus or input debounces an ajax request and the reponse is a list of something which i can click and set as value of the input. The component uses labled-input component which is similar to Vuetify text input.
How ever, I would like to change to code to somehow using slots but its a problem since I have to listen for emits ( focus, blur ) from that slot.
So instead of my-labeled-input wanna change it to <slot></slot> and pass component from parent. The idea is to use the same code for selects too. Any suggestions?
<template> <div class="my-autocomplete"> <my-labeled-input :value="value" :title="title" @input="lInput" @focus="onFocus" @blur="onBlur"></my-labeled-input> <div class="list-container" v-if="focused"> <ul class="menu" v-if="list.length > 0"> <li v-for="item in list" @mousedown="itemClick(item.toponymName)">{{ item.toponymName }}</li> </ul> <template v-else> <p v-if="waiting"> Loading ...</p> <p v-else>No Data</p> </template> </div> </div> </template> <script> import debounce from 'lodash.debounce'; import myLabeledInput from '../../components/my-labeled-input/index.vue'; export default { name: 'my-autocomplete', components: { myLabeledInput, }, props: { value: { type: String, default: null, }, title: { type: String, default: null, }, apiUrl: { type: String, default: null, }, query: { type: Object, default: () => {}, }, debounceInterval: { type: Number, default: 1000, }, }, data() { return { list: [], focused: false, waiting: false, }; }, methods: { lInput(value) { this.$emit('input', value); this.waiting = true; this.getList(value); }, onFocus() { this.focused = true; this.waiting = true; this.getList(this.value); }, onBlur() { console.log('blur'); this.focused = false; }, getList: debounce(function (value) { // eslint-disable-line this.$http({ url: this.apiUrl, method: 'GET', params: { ...this.query, name_startsWith: value, }, }).then((response) => { console.log(response); this.list = response.data.geonames; this.waiting = false; }).catch(() => { this.list = []; this.waiting = false; }); }, 2000), itemClick(value) { this.$emit('input', value); }, }, }; </script>