Software
Why v-model attribute work differently
Two equal examples (according to Vue.js) work differently:
First
<input v-model="value" @input.once="setDirty" type="text" id="object-email">Second:
<input v-bind:value="value" v-on:input="value = $event.target.value" @input.once="setDirty" type="text" id="object-email">In the first example value changes only after second input, while the second example works correctly. If we delete @input.once attribute, two examples will work fine.
P.S. Vue 2.4.0
How does this import statement work?
I just downloaded a template from a vue cli as
vue init webpack my-project.
and inside Hello.vue I saw an import statement like this.
import Hello from '@/components/Hello';
and I am curious what does that @ does. It's used at a lot of places but no where it's written what exactly it does. Would be great if someone can explain what it does?
Trying to edit data in VueJS while using watch
I have been trying to learn VueJS, and for the most part I have everything working. I am running into a issue when I double click on a label, to edit that entry, it will turn into a input but then quickly switch back to a label (not allowing me to edit the entry). Now if I comment out the watch, it works but then of course it will not show the updated data (unless I refresh the page). Why can I not edit something, while I am using watch?
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="index.css"> </head> <body> <section class="todoapp"> <input class="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" v-model="newTodo" @keyup.enter="addTodo"> <section class="main" v-show="todos.length" v-cloak> <ul class="todo-list"> <li v-for="todo in todos" class="todo" :key="todo.id" :class="{ editing: todo == editedTodo }"> <div class="view"> <label @dblclick="editTodo(todo)">{{ todo.keyword }}</label> <button class="destroy" @click="removeTodo(todo)"></button> </div> <input class="edit" type="text" v-model="todo.keyword" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)"> </li> </ul> </section> </section> <script src="https://unpkg.com/vue@2.4.2/dist/vue.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script src="app.js"></script> </body> </html>app.js
var app = new Vue({ data: { todos: [], newTodo: '', editedTodo: null }, mounted() { axios.get('/cgi-bin/select.py').then((response) => { this.todos = response.data; }).catch((err) => { console.log(err); }); }, watch: { todos: function () { axios.get('/cgi-bin/select.py').then((response) => { this.todos = response.data; }).catch((err) => { console.log(err); }); } }, methods: { addTodo: function () { var value = this.newTodo && this.newTodo.trim() if (!value) { return } axios.post('/cgi-bin/blacklist_insert.py', { keyword: value }) .then(response => { console.log(response.data) }) .catch(function (error) { console.log(error); }); this.newTodo = '' }, removeTodo: function (todo) { axios.post('/cgi-bin/delete.py', { id: todo.id }) .then(response => { console.log(response.data) }) .catch(function (error) { console.log(error); }); }, editTodo: function (todo) { this.beforeEditCache = todo.keyword this.editedTodo = todo }, doneEdit: function (todo) { if (!this.editedTodo) { return } this.editedTodo = null todo.keyword = todo.keyword.trim() if (!todo.keyword) { this.removeTodo(todo) } axios.post('/cgi-bin/update.py', { id: todo.id, keyword: todo.keyword }) .then(response => { console.log(response.data); }) .catch(function (error) { console.log(error); }); }, cancelEdit: function (todo) { this.editedTodo = null todo.keyword = this.beforeEditCache } }, directives: { 'todo-focus': function (el, binding) { if (binding.value) { el.focus() } } } }) app.$mount('.todoapp')Vue2 - Convert Vanilla ONKEYPRESS Function To Method
I'm trying to limit the amount of characters entered on a content editable div.
This works correctly...
<div onkeypress="return (this.innerText.length >= 140 ? false : true )">However, I need to run this as a Vue method (in single file component). I'm trying to do the following, but can't get it to work:
<div @keypress="limitTextChar"> // data props: { limitText: { type: Boolean, default: false }, limitLength: { type: Number, default: 140 } } limitTextChar(event) { return this.limitText && event.target.innerText.length >= this.limitLength ? false : true }Where am I going wrong?
Vue array to table issues
Having some issues printing array data to a table using Vue. Can someone help me parse the values using vue and put them in a table. See code below image. Without the array of 2 it would work but I'm not sure how to with the response being multiple.
This is my function in due
//HTML CODE
<tbody> <tr v-for="(input, index) in inputs"> <th>((input.id))</th> <th>((input.tracking_number))</th> <td>((input.first_name))</td> <td>((input.last_name))</td> <td>((input.weight))</td> <td>((input.description))</td> <td>((input.courier))</td> </tr> </tbody>//end HTML
//Vue Code
var app = new Vue({ el: '#app', data: { inputs: [], form: { scanval: null } }, methods: { updatetable() { this.$http.get('someroute', {params: {page: this.form}}) .then(response => { if (response.body != "null") { console.log(response); this.inputs.push({ id: response.body.id, tracking_number: response.body.tracking_number, first_name: response.body.first_name, last_name: response.body.last_name, weight: response.body.weight, description: response.body.description, courier: response.body.courier }) this.form.scanval = "" } else { this.form.scanval = "", alert("No items found") } }, response => { alert("no item found"); }); },Trying to save an image with Vue.js and axios on Laravel 5.5
I am using Laravel 5.5, Vue.js and axios.
I am generating a canvas image from a particular element. The code for saving an image:
save(url) { let element = document.getElementsByClassName('preview'); html2canvas(element, { proxy: url, onrendered: function(canvas) { var image = canvas.toDataURL("image/jpeg"); console.log(image); Vue.axios.post('/add', { image: image, }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); // downloadURI("data:" + image, "yourImage.jpg"); } }); }This is the code from controller:
public function addPost(Request $request) { $photo = $request->file('image'); $path = $request->photo->store('img'); return 'something'; }But all I am getting is this error: Call to a member function store() on null. So the error is in $path.
I have tried with if($request->hasFile('image')) but it doesn't do nothing. What should I do, so I can store generated image to my public derictory?
Vuex - Computed property "name" was assigned to but it has no setter
I have a component with some form validation. It is a multi step checkout form. The code below is for the first step. I'd like to validate that the user entered some text, store their name in the global state and then send then to the next step. I am using vee-validate and vuex
<template> <div> <div class='field'> <label class='label' for='name'>Name</label> <div class="control has-icons-right"> <input name="name" v-model="name" v-validate="'required|alpha'" :class="{'input': true, 'is-danger': errors.has('name') }" type="text" placeholder="First and Last"> <span class="icon is-small is-right" v-if="errors.has('name')"> <i class="fa fa-warning"></i> </span> </div> <p class="help is-danger" v-show="errors.has('name')">{{ errors.first('name') }}</p> </div> <div class="field pull-right"> <button class="button is-medium is-primary" type="submit" @click.prevent="nextStep">Next Step</button> </div> </div> </template> <script> export default { methods: { nextStep(){ var self = this; // from baianat/vee-validate this.$validator.validateAll().then((result) => { if (result) { this.$store.dispatch('addContactInfoForOrder', self); this.$store.dispatch('goToNextStep'); return; } }); } }, computed: { name: function(){ return this.$store.state.name; } } } </script>I have a store for handling order state and recording the name. Ultimately I would like to send all of the info from multi step form to the server.
export default { state: { name: '', }, mutations: { UPDATE_ORDER_CONTACT(state, payload){ state.name = payload.name; } }, actions: { addContactInfoForOrder({commit}, payload) { commit('UPDATE_ORDER_CONTACT', payload); } } }When I run this code I get an error that Computed property "name" was assigned to but it has no setter.
How do I bind the value from the name field to the global state? I would like this to be persistent so that even if a user goes back a step (after clicking "Next Step") they will see the name they entered on this step
Vue.js 2.0 Component and Parent
I am having an issue and please forgive me for being relatively new to vue. I have this component:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script> <template> <table class="table table-bordered table-hover table-responsive"> <thead> <tr> <th>File Number</th> <th>Client</th> <th>Borrower</th> <th>Address</th> <th>City</th> <th>State</th> <th>Zip</th> <th>Appraiser ID</th> <th>Paid Status</th> <th>Process Status</th> <th>Order Status</th> <th>Last Update Time</th> <th>Loan Number</th> <th>Due Date</th> <th>Appraiser Due Date</th> </tr> </thead> <tbody> <tr @click="onSelected(order)" data-toggle="tab" href="#orders" role="tab" aria-controls="orders" v-for="order in orders"> <td>{{order.id}}</td> <td>{{order.client_id}}</td> <td>((Jackson))</td> <td>{{order.address1}}</td> <td>{{order.city}}</td> <td>{{order.state}}</td> <td>{{order.zip}}</td> <td>{{order.appraiser_id}}</td> <td>{{order.paid_status_id}}</td> <td>{{order.process_status}}</td> <td>{{order.order_status}}</td> <td>{{order.last_update}}</td> <td>{{order.loan_number}}</td> <td>{{order.due_date}}</td> <td>{{order.appraiser_due_date}}</td> </tr> </tbody> </table> </template> <script> export default { /* * The component's data. */ data() { return { orders: [] }; }, /** * Prepare the component (Vue 1.x). */ ready() { this.prepareComponent(); }, /** * Prepare the component (Vue 2.x). */ mounted() { this.prepareComponent(); }, methods: { onSelected: function(order) { CurrentOrder.$emit('updateCurrentOrder', order); }, /** * Prepare the component (Vue 2.x). */ prepareComponent() { this.getPrecedenceOrders(); }, /** * Get all of the precedence orders for the user. */ getPrecedenceOrders() { axios.defaults.baseURL = 'https://someurlgoeshere'; axios.get('/api/makeacallsomewhere', { headers: { 'Content-Type' : 'application/json', 'Accept' : 'application/json', 'Authorization' : 'Bearer ' + token, } }) .then(response => { this.orders = response.data; }); } } } </script>
This has worked really well for me. However, at this point I am a little lost and I understand this question may be too vague and or not specific enough for this community. The @click="onSelected(order)" is supposed to update the order information in the orders tab. However, I can't get that to work. Can anyone help me out with an example in how to do that? The orders tab will have a separate component.
If this is too vague please just let me know and I can remove this question.
Thanks!
waypoint Uncaught TypeError: Cannot read property 'each' of undefined
I am using waypoint and it send me this message:
Uncaught TypeError: Cannot read property 'each' of undefined
this is how I got the code with vue.js + rails:
<template> <div id="playerContainer final"> <iframe src="xxxxxxxxx" allowfullscreen></iframe> </div> </template> <script> require('waypoints/lib/jquery.waypoints.min.js') export default { mounted(){ var ele new Waypoint({ element: ele = document.getElementById('final'), handler: function(direction) { if (direction == 'down') { $(ele).addClass('muestra') } else { $(ele).removeClass('muestra') } console.log(direction); } }); } } <script>I will really appreciate guys if you ca help me with this issue.
How do I access the $route.params variable in the component resolve function
I have a simple website that uses async components. Here's an example of one:
Vue.component('news', function(resolve, reject){ let data = { action: 'load_news_article', article_id: 0 // need the article ID here }; $.post(window.ajax_url, data, function(r){ r = JSON.parse(r); if( r.success ) { resolve({ template: r.data }); } }); });I have dynamic routes that map to this component as well. Those <router-link> URL's look like /news/some-article. I created the route as /news/:article in the router.
How can I access the article variable before firing my ajax? My goal is to pass it to the server along with the initial component load. If Vue doesn't allow that, then I can't think of any other way other than letting the router navigate the page, then I parse the new URL with my own JS.
It's a really simple website. There's only 5 components (one for each page) and only this one is dynamic. So I'm looking for a solution that doesn't require me to overhaul my structure.
Flat file CMS with JSON output
I am trying to create a simple site with flat-file content management, and a Vue.js front-end. I hope to approximate the following file structure:
app - various vue files and folders - data.json - posts - - post1.md - - post2.mdThere would be some kind of build process that takes each markdown file in app/posts, processes the markdown, and stores everything in app/data.json. Then the vue.js front-end can just import data.json and use it to hydrate various components as needed.
The problem I am having in finding a solution is that there are tons of flat-file CMS out there, but very few of them seem to allow you to get between the processing of the flat files and the rendering of the templates. Most of the flat-file CMS I have encountered are designed to generate a static site folder structure of html documents. Since I intend to use a front-end framework with routing (I am using Vue, but it could be React, Choo, etc.), I need a flat-file CMS that will easily dump the data it processes from the folder structure into a single JSON file that can be adapted to serve as the data model for Vue.
I've Googled this many times and in many ways. The fact that so few results come back, in spite of the omnipresence of front-end js frameworks, is making me wonder if there's some obvious reason you wouldn't build a site this way, or some key term I'm missing.
So, my questions:
Is there a flat-file CMS that allows you to easily harvest the data it extracts without generating a full static site?
If not, why? Is it that the processing of a folder full of markdown files is simple enough that it should just be done with a custom npm script? Is there a glaringly obvious reason that generating a js-framework-friendly mini-database from a flat file system is a dumb idea?
TypeScript can't find imports inside Vue class component when trying to reify $refs even though they can be accessed when adding them as components?
I'm making a Vue 2.0 Progressive Web App with the Quasar Framework, and I'm trying to make the drawer in the left slot of the layout close when a menu item is clicked.
This is the component script Home.ts:
import Vue from 'vue'; import Component from 'vue-class-component'; import { QIcon, QLayout, QList, QListHeader, QItem, QItemMain, QItemSide, QToolbar, QToolbarTitle, } from 'quasar'; @Component({ name: 'Home', components: { QIcon, QLayout, QList, QListHeader, QItem, QItemMain, QItemSide, QToolbar, QToolbarTitle, } }) export default class Home extends Vue { $refs: { layout: QLayout // Cannot find name 'QLayout' }; public newPainting() { this.$refs.layout.toggleLeft(); this.$router.push(`painting/new`); } }This doesn't compile because of the Cannot find name 'QLayout' error, but when I change the type of this.$refs.layout to any, it works.
I'm confused as to why it can't find QLayout, since it's being used in the @Component() decorator.
This is the Home.vue file for the component (mostly taken from the default one you get when you use quasar-cli to scaffold a layout):
<template> <q-layout ref="layout"> <q-toolbar slot="header"> <!-- opens drawer below--> <button class="hide-on-drawer-visible" @click="$refs.layout.toggleLeft()"> <q-icon name="menu"></q-icon> </button> <q-toolbar-title> echroma </q-toolbar-title> </q-toolbar> <!-- Left Side Panel --> <div slot="left"> <q-list no-border link inset-delimiter> <q-list-header>Menu</q-list-header> <q-item @click="newPainting()"> <q-item-side icon="add_to_photos" /> <q-item-main label="New Painting" sublabel="Start evolving a new painting!" /> </q-item> </q-list> </div> <router-view /> </q-layout> </template> <script> import Home from './Home' export default Home </script> <style> </style>Is there any reason why QLayout wouldn't be accessible from inside the class declaration?
Laravel 5.4 Vue.JS example failed to mount
Starting with Vue.js and wanted to give it a try to the example that comes with laravel.
No component is displayed and in console I get
[Vue warn]: Failed to mount component: template or render function not defined. found in ---> <Example> <Root>Not a fresh install, upgraded from 5.2->5.3->5.4
resources/assets/js/app.js
/** * First we will load all of this project's JavaScript dependencies which * includes Vue and other libraries. It is a great starting point when * building robust, powerful web applications using Vue and Laravel. */ require('./bootstrap'); window.Vue = require('vue'); /** * Next, we will create a fresh Vue application instance and attach it to * the page. Then, you may begin adding components to this application * or customize the JavaScript scaffolding to fit your unique needs. */ Vue.component('example', require('./components/Example.vue')); const app = new Vue({ el: '#app' });resources/assets/js/components/Example.vue
<template> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-heading">Example Component</div> <div class="panel-body"> I'm an example component! </div> </div> </div> </div> </div> </template> <script> export default { mounted() { console.log('Component mounted.') } } </script>This is the blade in which I have the js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Testing</title> <link rel="stylesheet" href="css/app.css"> <meta name="csrf-token" content="{{ csrf_token() }}"> </head> <body> <div id="app"> <example></example> </div> <script src="js/app.js" charset="utf-8"></script> </body> </html>What's the best way to send an object to a component with nested data using Vue?
Let's say I have the following data:
data: function() { return { a: "hello", b: { title: this.a + " BOB"; } } }When I pass this in a component, the this.a is undefined.
<component :pass-data="b"></component>How do I send that nested property?
Module build failed: Error: ENOENT: no such file or directory, open ... at Error (native) @ multi (webpack)-dev-server/client?
I build small project with vue.js here my code in main.js
import Vue from 'vue' import App from './App.vue' new Vue({ el:'#app', render:h => h(App) })` that error appear when I saved my style and reloade the page enter image description here
after mode: 'history' vue router doesn't work
I started learning vuejs recently and build and app with firebase for authetication. I got a problem after i installed the webpack theme and tried to remove the default hashtag on links. When i insert the mode:history it doesnt redirect me after i login to my hello page. When i remove it everything works fine.
My index.js (under my router folder):
Vue.use(Router) const router = new Router({ mode: 'history', routes: [ { path: '*', redirect: '/login' }, { path: '/', redirect: '/login' }, { path: '/login', name: 'Login', component: Login }, { path: '/sign-up', name: 'SignUp', component: SignUp }, { path: '/hello', name: 'Hello', component: Hello, meta: { requiresAuth: true } } ] }) router.beforeEach((to, from, next) => { let currentUser = firebase.auth().currentUser; let requiresAuth = to.matched.some(record => record.meta.requiresAuth); if (requiresAuth && !currentUser) next('login') else if (!requiresAuth && currentUser) next('hello') else next() }) export default routerPls let me know if you need anything else for solving my issue.
Sanitizing HTML Input with Trix
I have a strange issue at the moment, and I'm looking for any insight on how to deal with this.
I'm currently accepting HTML input using the Basecamp Trix editor.
When I send the input to my Laravel application, it is saved to my database as:
<div><script>alert('test');</script></div>However, the problem is that when I insert this into a Vue property using Laravel's blade, it actually converts it back into valid HTML:
<reply :data-reply="{{ $reply }}"></reply>Result:
The problem is, I can't sanitize this because the HTML data is actually escaped in my database, but when Laravel converts my reply to JSON, it actually unescapes the script tags, and it's actually ran in Vue when using the v-html directive.
I know I'm not supposed to accept user input while using the v-html directive, but I need HTML support for replies, and I can't sanitize already escaped HTML in my Laravel application.
Does anyone have any ideas how I can go about sanitizing Trix's content in some way?
Rendering an email preview in Vue
I'm creating an internal messaging app in Vue and would like to expose a limited number of predefined variables for a user to choose from when sending a templated message (name, department, etc.).
I'm planning on displaying the rendered variables in a "preview" component which ideally would take the raw html, complete with {{variables}}, fetch the values for the variables and render the preview.
Judging from https://vuejs.org/v2/guide/components there are a number of options that would seem to work, is there an objectively better/worse solution?
Vue.js: anonymous function with parameter in v-on:event or @event
I want to execute a simple function after an event is emitted from the child component. The problem is the child component emits data that I need as a parameter for my function.
How can I inject the parameter and run the function in one line in the component?
<div v-on:posted="runTask"> </div>Or
<div @posted="runTask"> </div>Important: I would like it to fit in the template (v-on:event or @event) because I want to keep the component in the PHP blade template.
VueJS list ordering based on async child-gathered data
I have an interesting situation as follows. I have:
- a parent component that does a web service call for a list of results (websites)
- it then renders a "result item" component (v-for) for each result
- then each "result item" component fires off a number of web service calls to get scores for that url and display them beside it.
Basically the component tree is:
- page
- result item (many)
- x score
- y score
- z score
- result item (many)
Up until now I've been able to pass down the tree using props just the web url of the result item to the scoring components and keep the score service call and data local to each score component. This nicely separates all the logic.
Nonetheless, what I'd like to achieve now is:
- Result items v-for list re-orderable based on the "x score", "y score", "z score" async calculated values via user-controlled dropdowns on the page component (e.g. order by x/y/z dropdown and asc/desc dropdown).
- Results list re-order as the score values come in async-ly (i.e. reactive upfront)
I've been looking at Vuex, and it seems like it may be the best approach but before I dive all the way in I'd like to verify my thoughts and if people think it'd actually work.
Should I:
- Use a Vuex store to hold my list of results
- Use a mutation to store the initial results list (list of objects with id/url)
- Use a computed property in the page component like "orderedResults" and render the "result item" components with v-for from that
- Use mutations on each scoring component to add the scores to each result item in the store (prob with set method to ensure reactivity on new prop). And does this mean I need to pass an id of the result item and the new score then do a lookup in the result items by id to find and modify it, or can I pass through in the mutation payload the ref I have of the result item given down via props and just use that in the mutation function directly?
Is this the best way to do it? Any gotchas? Thanks!