Software

nuxt can't use vue-factory in asyncMethod & fetch method

Vuejs - Wed, 2017-08-30 09:25

iam using vue-factory to inject some service in my nuxt app (vue-ssr). the problem is i can't use my service in asyncMethod & fetchMethod in nuxt. The service can only running on browser event (in mounted and methods);

i have trying this to add my service on context method in nuxt, but its raise an error in browser Cannot redefine property: $Vue

import Vue from 'vue'; import factory from 'vue-factory'; import postService from '../service/postService'; import commentpostService from '../service/commentpostService'; Vue.use(factory); Vue.factory.register({ 'postService': postService, 'commentpostService': commentpostService, }); export default ({ app, store }) => { Vue.factory.register({ 'postService': postService, 'commentpostService': commentpostService, }); // app.postService = postService; // app.commentpostService = commentpostService; }

can anyone solve this

Categories: Software

Passing Data from Node-Express backend to Vue component

Vuejs - Wed, 2017-08-30 09:07

I'm still learning Vue.js 2 so I do apologize if this question is a bit silly. I'm building an application using MongoDB, Node, Express and Vue. Normally I'd use a template engine such as Ejs where data passed through Express's res.render method can be readily captured in the template.

Is there a similar way to pass data from backend to the root Vue component? For example, normally, a get request fetches some data from Mongodb, express will render the template file and pass data to it.

app.get("/gallery/:id", function(res, req) { var id = req.params.id; database.findById(id, function(err, data) { .... res.render("home", data); } });

Now my root Vue application is attached to html file. I'd like to be able to dynamically render the app with data returned from the database.

I've built an app before that streams data from an api and passed it to my Vue component via socket but I feel like using a socket in this case is unnecessary.

Categories: Software

How to make login in vue js 2 and laravel 5.4?

Vuejs - Wed, 2017-08-30 07:41

Signin form:

<form @submit.prevent="signIn()" enctype="multipart/form-data"> <div class="form-group" :class="{'has-error': errors.has('login.signin_mobile_number') }" > <input v-model="login.signin_mobile_number" name="signin_mobile_number" v-validate="'required'" class="form-control" type="number" placeholder="Mobile Number"> </div> <div class="form-group" :class="{'has-error': errors.has('login.signin_password') }" > <input v-model="login.signin_password" name="signin_password" v-validate="'required'" class="form-control" type="password" placeholder="Password"> </div> <a href="" class="frgt-pwd">Forgot Password? </a> <div class="modal-footer btn-center"> <button type="submit" class="btn btn-default">Sign In</button><br><br> <a href="" data-dismiss="modal" id="signin"> Or Sign Up </a> </div> </form>

script:

export default { data() { return { login: { signin_mobile_number: '', signin_password= '', } } }, methods: { signIn() { this.$validator.validateAll().then((result) => { }); axios.post(config.apiDomain+'/Login',this.login).then(response=>{ this.login=""; }); }, signUp() { this.$validator.validateAll().then((result) => { }); axios.post(config.apiDomain+'/Register',this.register).then(response=>{ this.register=""; }); }, } }

Login Controller:

<?php namespace App\Http\Controllers; use App\Login; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Auth; class LoginController extends Controller { public function authenticate() { $mobile_number = $request->get('mobile_number'); $password = $request->get('password'); if (Auth::attempt(['signin_mobile_number' => $mobile_number, 'signin_password' => $password])) { // Authentication passed... return redirect()->route('Home'); } else { return redirect()->back() ->with('message','Incorrect email or password') ->with('status', 'danger') ->withInput(); } } public function store(Request $request) { $input = $request->all(); Login::create($input); } }

The register form also:

<form @submit.prevent="signUp()"> <div class="form-group" :class="{'has-error': errors.has('mobile_number') }" > <input v-model="register.mobile_number" name="mobile_number" v-validate="'required'" class="form-control" type="number" placeholder="Mobile Number"> </div> <div class="form-group" :class="{'has-error': errors.has('email') }" > <input v-model="register.email" name="email" v-validate="'required'" class="form-control" type="email" placeholder="Email"> </div> <div class="form-group" :class="{'has-error': errors.has('password') }" > <input v-model="register.password" v-validate="'required|confirmed:confirm_password'" name="Password" class="form-control" type="password" placeholder="Password"> </div> <div class="form-group" :class="{'has-error': errors.has('confirm_password') }" > <input v-model="register.confirm_password" name="confirm_password" class="form-control" type="password" placeholder="Confirm Password"> </div> <div class="modal-footer btn-center"> <button type="submit" class="btn btn-default">Sign Up</button> </div> </form>

The above were the codes that i have used to do sign in functionality, Here i have given a form with signIn() method and i have made a api call inside it and the values are getting stored in database.. But the thing is i need to do login for the registered user only .(i.e,) if i give any details inside login it taking and storing in db but i need to restrict this that only registered user has to get login otherwise error message needs to be displayed, i am new with laravel so kindly let me know how should i make the change in the controller for login only by registered user.

Categories: Software

Nested transition modal

Vuejs - Wed, 2017-08-30 07:05

i'm creating modal with vuejs and following this example but i create a separated file for modal so i can simply call my modal component anywhere i need to like this

here is my modal.vue

<template> <div class="modal-mask" @click="close"> <div class="modal-dialog" :class="size"> <div class="modal-content"> <div class="modal-header" :class="color"> <button type="button" class="close" @click="close">&times;</button> <h6 class="modal-title">{{ title }}</h6> </div> <div class="modal-body"> <slot></slot> </div> <div class="modal-footer"> <slot name="button"></slot> </div> </div> </div> </div> </template> <script> export default{ props: ['title','color','size'], methods: { close(){ this.$emit('close'); } } } </script> <style> .modal-mask { position: fixed; z-index: 9998; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, .5); transition: opacity .3s ease; } </style>

and in index.vue where i want to call it i just simply

<app-modal :title="modalTitle" :size="modalSize" :color="modalColor" v-if="modalShow" @close="modalShow = false" > </app-modal>

now my question is i want to use 2 kind of transition, first is in my index.vue page

<transition name="modal"> <app-modal :title="modalTitle" :size="modalSize" :color="modalColor" v-if="modalShow" @close="modalShow = false" > </app-modal> </transition>

and the second one is in my modal.vue like this

<template> <div class="modal-mask" @click="close"> <transition name="modal-inside"> <div class="modal-dialog" :class="size"> <div class="modal-content"> <div class="modal-header" :class="color"> <button type="button" class="close" @click="close">&times;</button> <h6 class="modal-title">{{ title }}</h6> </div> <div class="modal-body"> <slot></slot> </div> <div class="modal-footer"> <slot name="button"></slot> </div> </div> </div> </transition> </div> </template>

why i want it like that well simply because in there is modal-mask class that warp entire modal and that css class is add some dark/shade background so user can focus on the modal.... exactly like bootstrap modal fade effect and then after that i want everything inside div modal-dialog to show/transition after modal-mask is already finished its transition

so it will just first darken background and then show modal... they move separately one after another.. not at the same time

or to be more easy to imagine it i want to generate exactly like bootstrap modal

Categories: Software

Vue router scrollBehavior returns same path for both to and from

Vuejs - Wed, 2017-08-30 07:01

I would like to check the to and from of the route path with scrollBehavior to manage the scroll behaviour.

global.router = new VueRouter({ routes, scrollBehavior(to, from, savedPosition) { console.log('>>> to', to); console.log('>>> from', from); switch (to.path) { case '/in-list': break; case '/your-list': break; default: return {x: 0, y: 0} } }, mode: 'history', });

Suppose, I navigate from About page to the In-List or Your-list page, I would like to return {x: 0, y: 0}. However, when navigating between In-list or Your-list I would like no such behaviour.

However, both to and from return the same path. They both return the to.path so I cannot check where it was navigated from. What am I missing here?

Categories: Software

Computed property on child component props

Vuejs - Wed, 2017-08-30 04:22

i'm having this setup where i have child component props that have datetime format inside it and i want to change it to more human readable format in my table, so i use moment js to change the format and to do those kind of task it will be make more sense if i use computed property. Like this in my index.vue

<div class="page-container"> <div class="page-content"> <div class="content-wrapper"> <data-viewer :source="source" :thead="thead"> <template scope="props"> <tr> <td>{{props.item.name}}</td> <td>{{props.item.creator}}</td> <td> <i class="icon-checkmark5" v-if="props.item.publish === '0'"></i> <i class="icon-cancel-circle2" v-else></i> {{props.item.publish}} //for testing purpose to see returned value </td> <td>{{publishDate}}</td> //this is where i put my computed to change created_at format </tr> </template> </data-viewer> </div> </div> </div> <script type="text/javascript"> import DataViewer from '../../components/dataviewer.vue' import moment from 'moment' export default{ components:{ DataViewer }, data(){ return{ source: '/api/article', thead: [ {title: 'Name', key: 'name', sort: true}, {title: 'Creator', key: 'creator_id', sort: true}, {title: 'Publish', key: 'publish', sort: true}, {title: 'Created', key: 'created_at', sort: true} ], } }, computed: { publishDate: function(){ return moment(props.item.created_at).format('YYYY-MM-DD') } } } </script>

and here is what inside my dataviewer file

<template> <table class="table"> <thead class="bg-primary"> <tr> <th v-for="item in thead"> <span>{{item.title}}</span> </th> </tr> </thead> <tbody> <slot v-for="item in model.data" :item="item"></slot> </tbody> </table> </template> <script> import Vue from 'vue' import axios from 'axios' export default { props: ['source', 'thead'], data() { return { model: { data: [] }, } }, beforeMount() { this.fetchData() }, methods: { fetchData() { var vm = this axios.get(this.source) .then(function(response) { Vue.set(vm.$data, 'model', response.data.model) }) .catch(function(error) { console.log(error) }) } } } </script>

but it just won't work, it can't find props.item.created_at, so how i can change created_at or any other property item to change from my index.vue?

Categories: Software

Nested Components and Proper Wrapping Techniques in VueJS

Vuejs - Wed, 2017-08-30 02:28

I'm trying to put Bootstrap Select2 in a Vue wrapper. Somehow, my code works. But It doesn't seem proper to me.

I found a reference in here https://vuejs.org/v2/examples/select2.html In the VueJS website example, the el is empty. I didn't stick to this concept where in the new Vue part, they included a template because my el have sidebars and other stuffs also. What I did was I added a

<admin-access></admin-access>

to a section in the HTML.

I think I made my component nested which I'm skeptical if it is proper in VueJS.

Is there a better way to code this?

Templates

<template id="select2-template"> <select> <slot></slot> </select> </template> <template id="admin-access"> <div> <transition name="access" enter-active-class="animated slideInRight" leave-active-class="animated slideOutRight" appear> <div class="box box-solid box-primary" v-if="admin" key="create"> <div class="box-header with-border"> <i class="fa fa-text-width"></i> <h3 class="box-title">Create Admin</h3> </div> <div class="box-body"> <form action="" class="search-form"> <div class="form-group"> <label for="search_user_admin">Search User</label> <select2 name="search_user_admin" id="search-user-admin" class="form-control select2" :options="options" v-model="selected"> <option disabled value="0">Select one</option> </select2> </div> </form> </div> </div> </transition> </div> </template>

Script

Vue.component('admin-access', { template: '#admin-access', props: ['options', 'value'], created: function() { $('#search-user-admin').select2({ placeholder: "Select User", allowClear: true }); }, data: function() { return { admin : true, selected : false } }, }); Vue.component('select2', { template: '#select2-template', data: function() { return { selected: 0, options: [ { id: 1, text: 'Hello' }, { id: 2, text: 'Darkness' }, { id: 3, text: 'My' }, { id: 4, text: 'Old' }, { id: 5, text: 'Friend' } ] } }, mounted: function() { var vm = this; $(this.$el).select2({ data: this.options, placeholder: "Select an option", }) .val(this.value) .trigger('change') .on('change', function () { vm.$emit('input', this.value); }); }, watch: { value: function (value) { $(this.$el).val(value).trigger('change'); }, options: function (options) { $(this.$el).select2({ data: options }); } }, destroyed: function () { $(this.$el).off().select2('destroy'); } }); var admin = new Vue({ el: '#app' });
Categories: Software

Nuxt/ Vue - the html and js files it generates

Vuejs - Tue, 2017-08-29 23:26

I just started using Nuxt for server side rendering. It seems like a great framework. But I don't like about it is it generates lots of ugly html markups, js links, and the css is basically being dumped into the html directly. Also, you see lots of data-s. For example:

<!DOCTYPE html> <html data-n-head-ssr data-n-head=""> <head> <meta data-n-head="true" charset="utf-8"/><meta data-n-head="true" name="viewport" content="width=device-width, initial-scale=1"/><meta data-n-head="true" data-hid="description" name="description" content="Nuxt.js project"/><title data-n-head="true">Users</title><link data-n-head="true" rel="icon" type="image/x-icon" href="/favicon.ico"/><link rel="preload" href="/_nuxt/manifest.1dd9a3883f67d40b9aa7.js" as="script"><link rel="preload" href="/_nuxt/common.992cf40ea79f7d7937d8.js" as="script"><link rel="preload" href="/_nuxt/app.2d1407798eb328e5c249.js" as="script"><link rel="preload" href="/_nuxt/layouts/default.1360f17fdf8a6083917d.js" as="script"><link rel="preload" href="/_nuxt/pages/users.a5ea843f780a24b7dfd7.js" as="script"><link rel="prefetch" href="/_nuxt/pages/index.3c2e71cd997494896cb8.js"><link rel="prefetch" href="/_nuxt/pages/users-name.353da70d66b2cb18c1c9.js"><link rel="prefetch" href="/_nuxt/pages/about.7e9c73cd5e6253d976d6.js"><link rel="prefetch" href="/_nuxt/layouts/dark.9d852c7e76764cd94b7c.js"><link rel="prefetch" href="/_nuxt/pages/tasks.67c8259c9b53f68ea9a3.js"><style data-vue-ssr-id="5e853cdc:0">body,html{background-color:#fff;color:#000;letter-spacing:.5px;font-family:Source Sans Pro,Arial,sans-serif;height:100vh;margin:0}footer{padding:20px;text-align:center;border-top:1px solid #ddd}a,a:focus,a:hover,a:visited{color:#000}.logo{width:100%;height:auto;max-width:400px;max-height:289px}.layout-enter-active,.layout-leave-to{-webkit-transition:opacity .5s;transition:opacity .5s}.layout-enter,.layout-leave-to{opacity:0}</style><style data-vue-ssr-id="c6f373dc:0">.progress[data-v-5b643829]{position:fixed;top:0;left:0;right:0;height:2px;width:0;-webkit-transition:width .2s,opacity .4s;transition:width .2s,opacity .4s;opacity:1;background-color:#efc14e;z-index:999999}</style><style data-vue-ssr-id="59c3f703:0">.title[data-v-2941d5fc]{margin:30px 0}.users[data-v-2941d5fc]{list-style:none;margin:0;padding:0}.user[data-v-2941d5fc]{margin:10px 0}</style> </head> <body data-n-head=""> <div id="__nuxt" data-server-rendered="true"><div class="progress" style="width:0%;height:2px;background-color:black;opacity:0;" data-v-5b643829></div><section class="container" data-v-2941d5fc><img src="/_nuxt/img/logo.a04e995.png" alt="Nuxt.js Logo" class="logo" data-v-2941d5fc><h1 class="title" data-v-2941d5fc> USERS </h1><ul class="users" data-v-2941d5fc><li class="user" data-v-2941d5fc><a href="/users/jona" data-v-2941d5fc> jona </a></li><li class="user" data-v-2941d5fc><a href="/users/jon" data-v-2941d5fc> jon </a></li><li class="user" data-v-2941d5fc><a href="/users/jonas" data-v-2941d5fc> jonas </a></li></ul></section></div><script type="text/javascript">window.__NUXT__={"layout":"default","data":[{"users":[{"_id":"59a53db03a35535198135b15","id":null,"name":"jona"},{"_id":"59a53ded3a35535198135b17","id":null,"name":"jon"},{"_id":"59a574afd5bc922f3dbf8b68","id":null,"name":"jonas"}]}],"error":null,"serverRendered":true};</script><script src="/_nuxt/manifest.1dd9a3883f67d40b9aa7.js" defer></script><script src="/_nuxt/layouts/default.1360f17fdf8a6083917d.js" defer></script><script src="/_nuxt/pages/users.a5ea843f780a24b7dfd7.js" defer></script><script src="/_nuxt/common.992cf40ea79f7d7937d8.js" defer></script><script src="/_nuxt/app.2d1407798eb328e5c249.js" defer></script> </body> </html>

This is plain ugly to me:

<div id="__nuxt" data-server-rendered="true"><div class="progress" style="width:0%;height:2px;background-color:black;opacity:0;" data-v-5b643829></div><section class="container" data-v-2941d5fc>

Why do I need id="__nuxt" for?

How can I build all the js files into one file - not sure if this is possible?

How can I not to embed the entire css into the html?

How is this going to effect SEO?

Categories: Software

How to add multiple input values to store in Vue

Vuejs - Tue, 2017-08-29 23:24

Trying to add to a store on click from an input. There would be multiple inputs with different parts of an objects info. How can I grab in input data from a method?

In this case, I'm working with packets via a store

<input label="Packet Name" v-model="packets.name" required><br> <input label="Packet Name" v-model="packets.folder" required><br> <button @click="addPacket">Add</button>

On the addPacket call how do I get the input data?

Full jsfiddle : https://jsfiddle.net/tga9sfcm/1/

Categories: Software

VueJS Data from API call not displaying

Vuejs - Tue, 2017-08-29 22:22

I hope you can help me with this. I am trying to dynamically display some buttons according to an API call. I just dont happen to manage to receive the data before the page renders.

new Vue({ el: '#app', data : function(){ return { results : [], } }, beforeCreate : function(){ axios.get('somesite') .then(function (response) { this.results = response.data; console.log(this.results); }) .catch(function (error) { console.log(error); }); }, })

and the html is:

<head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no"> <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> </head> <body> {% raw %} <div class="container"> <div id="app"> <div class="response_list"> <button class="entries" v-for="entry in results"></button> </div> </div> </div> {% endraw %} <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script type="text/javascript" src="{{ url_for('static', filename='js/index.js') }}"></script> </body> </html>
Categories: Software

Using click method and event handler on same input field in VueJs

Vuejs - Tue, 2017-08-29 21:58

I'm trying to use a click method and an event handler on the same input box.

Only addLocale works, while showTip does not. However, if I remove one, the other begins to work. I'm not getting any errors so it's really hard to debug.

Is there some type of "collision" between @click and @keyup events in VueJS?

Here's my input field

<input type="text" v-model="addLocation" @click="showTip('local')" @keyup.enter="addLocale" >

Here are my methods

methods: { showTip(type) { if (type === 'locale') { this.audienceTip = false this.localeTip = true } if (type === 'audience') { this.localeTip = false this.audienceTip = true } }, addLocale() { if (this.addLocation) { this.selectedLocations.push(this.addLocation) this.addLocation = '' } } }
Categories: Software

Prevent a v-model change in Vue

Vuejs - Tue, 2017-08-29 21:54

I have a list of tasks stored in an array in my data() method.

Is there a way I can prevent / reverse a change to an object when it's linked by a v-model directive?

For example (in a component):

<template> <tr v-for="task in tasks" :key="task.id"> <input @change="complete(task)" v-model="task.complete" type="checkbox" name="complete"> <td>{{ task.summary }}</td> </tr> </template> <script> export default { props: ['allowChanges'], data() { return { tasks: [], }; }, methods: { complete(task) { if (this.allowChanges) { // axios.post() etc. } else { // This doesn't work: task.complete = !task.complete } }, } } </script>

I've tried using watchers and methods, but can't seem to reverse / cancel the change when made with a v-model directive?

Categories: Software

Push input data to store in Vue

Vuejs - Tue, 2017-08-29 21:37

Trying to add an object from a text field. Basically, trying to set the object name and folder. Kinda learning off this fiddle, however, it doesn't use a store. As far as I can see, I need to like my v-model to the computed property. After that, on a addPacket method call, I should be able to reference my input. Obviously, though I'm not using the data: {} property, so I imagine that's throwing an error or leaving the new method undefined.

////In templates <template> <v-card-text> <v-text-field label="Packet Name" v-model="packets.name" required></v-text-field> <v-text-field label="Packet Name" v-model="packets.folder" required></v-text-field> <small>*indicates required field</small> </v-card-text> <v-card-actions> <v-spacer></v-spacer> <v-btn class="blue--text darken-1" flat @click.native="dialog = false">Close</v-btn> <v-btn class="blue--text darken-1" flat @click.native="dialog = false" @click="addPacket">Save</v-btn> </v-card-actions> </template> //// In script <script> import axios from 'axios' export default { name: 'packetgen', computed: { packets: function () { return this.$store.getters.packets } }, methods: { addPacket: function () { var packet = { value: false, name: '', folder: '', admin: 'Dan' } alert(packet.name) this.$store.dispatch('addPacket', packet) } } } </script> //Store file state: { packets: [ { value: false, name: 'Firm Memo', folder: '\\Firm Memo', admin: 6.0, packetDocuments: [] } }, getters: { // TODO: implement getters.. // packets: function (state) { return state.packets }, }, mutations: { addPacket: function (state, packet) { alert(packet) state.packets.push(packet) } }, actions: { addPacket: function (context, packet) { context.commit('addPacket') } }

What am I doing wrong?

NOTE: Obviously, this won't compile. I tried to strip it down to show my specific view, store, and scripts. Working on a codepen..

Categories: Software

Vue.js table is rendered outside

Vuejs - Tue, 2017-08-29 21:26

I am trying to render a table. The data is dynamic and comes from an array. It works fine, except: the table content is rendered outside of the table on top of the page.

I would like it to render inside the table. Would anyone be able to help?

This what the code looks like:

Vue.js:

Vue.component('word', { props: ['word-list'], template: '#word-template' }); new Vue({ el: '#root' });

HTML:

<div id="root"> <word :word-list="{{json_encode($commonWords) }}"></word> <template id="word-template"> <table class="table"> <thead> <tr> <th>Key</th> <th>Value</th> </tr> </thead> <tbody> <tr v-for="(value, key) in wordList" :wordList="wordList"> <td> @{{ key }} </td> <td> @{{ value }} </td> </tr> </tbody> </table> </template> </div>

Note: This is used with Laravel, thats why there is an @ before double curly braces.

Categories: Software

vue.js 2 routing in vue-material

Vuejs - Tue, 2017-08-29 19:59

I'm currently working on a web page what uses vue.js with vue-material. I made a similar menu like this.

My goal, that one of the menu item redirect the user to an another page. I tried as a official doc says:

<md-list-item @click="$refs.sidebar.toggle(); this.$router.push('/company');"> <md-icon>start</md-icon> <span>Starred</span> </md-list-item>

But I got a vue-warn message:

[Vue warn]: Error in event handler for "click": "TypeError: this.$router is undefined"

I tried the all version: $router.push('/company');,router.push('/company');,this.router.push('/company'); but stil does not works.

On the other hand i tried to surround the md-list-item with router-link tag but it didnt work as well.

How can I define the routing inline (in the @click section)?

Thx for the responses in advance!

Categories: Software

Is it idiomatic to update a property of a prop, without an event?

Vuejs - Tue, 2017-08-29 19:37

I pass the list of inputs as a prop,

v-for input in inputProps v-model input.value

Should I be using events, instead of v-model?

Passing an event to manually update a property of a value in a list would involve

[index]'path to property', would it not?

Categories: Software

How to Initialize Data Properties with Prop Values

Vuejs - Tue, 2017-08-29 18:05

Still a little bit young in VueJS but I'm loving every bit of it. But now, fixated somewhere.
I want to initialize some values in data() using values passed via props. This is so that I can be able to mutate them later on, since it is not recommended to mutate props inside a component. In fact the official docs recommend this property initialization using prop values as shown below:

{ props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }

I have something like the one below:

<template> <div class="well"> <!-- Use Prop value directly on the template: works (but of no help in initializing data) --> Department: {{department.name}} <!-- Use prop value but gotten via computed property: Works inside the template but not in the initialization --> Department: {{fetchDepartment.name}} <!-- Use the array I initialized with the prop value: Does not work --> Department: {{this_department.name}} </div> </template> <script> export default { name: 'test', props: ['department'], data() { return { this_department: this.department // below does not work either //this_department: this.fetchDepartment } }, created() { // shows empty array console.log(this.department) }, mounted() { // shows empty array console.log(this.department) }, computed: { fetchDepartment() { return this.department } } } </script>

As seen in the commented sections above, the initialization is not successful. Neither does the value of this.department appear either from the created() or the mounted() hooks. And note, I can see it is defined using the Chrome Vue Devtools. So my question is, how exactly should I initialize data() attributes using props values, or which is the best way of going around this issue?

Categories: Software

Props not being assigned to data() attribute in Vue

Vuejs - Tue, 2017-08-29 17:26

I am creating a Vue component, which should refresh restaurants depending on user dynamically selected filters.

Therefor I have to update the filteredRestaurants in the data() function of my Vue component. However, at first, when the Vue component is rendered, it takes the restaurant information from the "restaurants" prop.

I have tried to insert the "restaurants" into the filteredRestaurants data attribute to set it as a default value. Unfortunatelly then the stores wouldnt show at tall, as if the "restaurants" prop is inserted after the filteredRestaurants is assigned its value.

My question is, how can i get the "restaurants" prop into filteredRestaurants so that I can later on, re-render the Vue component when the user changes the filters.

<template lang="html"> <div class="test"> <Filters></Filters> <div> <ul class="o-list c-stores"> <Result v-bind:total="restaurants.length" v-bind:open="isOpen" v-on:toggle="toggleRestaurantList"></Result> <li v-for="(restaurant, index) in restaurants" class="c-stores__location" :class="{'first': isFirst(index), 'last': isLast(index, restaurants)}"> <Location :index="index" :store="restaurant" :link="() => setCurrentRestaurant(restaurant)"></Location> </li> </ul> </div> </div> </template> <script> import eventHub from './../../event-hubs/storefinder' import Location from './Location' import Filters from './Filters' import Result from './Result' export default { props: ["restaurants", "isOpen", "currentSearch"], data() { return { attributes : [], // Here I am assigning the prop filteredRestaurants : this.restaurants } }, head: { title: function () { return { inner: this.$t('storefinder.overview') } }, meta: function functionName() { return [{ name: 'og:title', content: this.$t('storefinder.overview') + ' - ' + this.$t('storefinder.name'), id: "og-title" }, { name: 'description', content: this.$t('storefinder.description'), id: "meta-description" }, { name: 'og:description', content: this.$t('storefinder.description'), id: "og-description" }, ] } }, components: { Location, Filters, Result }, methods: { toggleRestaurantList() { eventHub.$emit('showRestaurantList'); }, setCurrentRestaurant(restaurant) { this.trackRestaurantSelect(restaurant.publicNameSlug); this.$router.push({ name: "store", params: { restaurant: restaurant.publicNameSlug } }); }, trackRestaurantSelect(restaurantName) { dataLayer.push({ 'event': 'GAEvent', 'eventCategory': 'restaurants', 'eventAction': 'clickResult', 'eventLabel': restaurantName, 'eventValue': undefined, 'searchTerm': this.currentSearch && this.currentSearch.toLowerCase(), 'amountSearchResults': 1 }); }, created() { eventHub.$on('addFilterTheRestaurants', (attribute) => this.attributes.push(attribute)); eventHub.$on('removeFilterTheRestaurants', (attribute) => this.attributes = this.attributes.filter(item => item !== attribute)); }, isLast: function (idx, list) { return idx === list.length - 1; }, isFirst: function (idx) { return idx === 0; }, } } </script>

The only way this worked, was when I had the filteredRestaurants as a function which returned "restaurants", and I called it inside the Vue template:

filteredRestaurants(){ return this.restaurants }

Any help appreciated.

Categories: Software

Vue js method with argument and setTimeout

Vuejs - Tue, 2017-08-29 16:41

I can't figure out why this code works..

data: { return { userMinerals: 0, mineralsLimit: 1000, miners: 0, superMiner: 0, minerPrice: 10, superMinerPrice: 100, minersLimit: 10 } } methods: { counter() { setInterval(() => { this.userMinerals += this.miners; if(this.checkLimit(this.userMinerals, this.mineralsLimit)) { this.userMinerals = this.mineralsLimit; } }, 100); }, addMiner() { if (this.userMinerals >= this.minerPrice) { this.miners += 1; this.userMinerals -= this.minerPrice; this.counter(); } } }

.. but if I try to put parameters into counter() the code stops working

methods: { counter(typeOfCredits) { setInterval(() => { typeOfCredits += this.miners; if(this.checkLimit(this.userMinerals, this.mineralsLimit)) { typeOfCredits = this.mineralsLimit; } }, 100); }, addMiner() { if (this.userMinerals >= this.minerPrice) { this.miners += 1; this.userMinerals -= this.minerPrice; this.counter(this.userMinerals); } } }

From the console I can see that typeOfCredits gets incremented as it should but it doesn't update the value in the view. Thx for help

Categories: Software

Directive v-if doesn't work when changing tab

Vuejs - Tue, 2017-08-29 15:43

I'm trying to build a simple listing system that shows a list of items for different platforms, each platform is on a seperate tab . I created the tab switching logic via VueJS from scratch .

What I'm doing:

Basically I have two platforms : twitter and facebook, when user click on one of the tabs, the frontend send an ajax request to my server to fetch posts for that platform and render them via v-for .

I added a button called edit for each post, when user press it , it calls a function edit(p), where p is the current post that user want to edit .

in edit(p) I change an atrribute p.editing which using v-if shows a text area and a timepicker (I'm using flatpicker) for that post .

What's Wrong:

All this works fine when I'm on the first tab, but once I switch the tab, it stop working, after debugging I noticed that v-if is not working event p.editing is updated when edit(p) is called, here's the code :

var posts_app = new Vue({ el: "#posts_app", data: { platforms : ['facebook','twitter'], current_tab: { 'facebook' : true, 'twitter': false }, platform_posts: { 'facebook': [], 'twitter': [] }, posts: undefined, }, methods:{ showTab: function(i){ platform = this.platforms[i] // UI stuff : to make the clicked tab active for(p in this.current_tab){ if(p == platform){ this.current_tab[p] = true } else{ this.current_tab[p] = false } } // Show content by platform this.posts = this.platform_posts[platform] }, edit: function(p){ p.editing = true console.log(p) Vue.nextTick(function(){ document.getElementsByClassName("dt-input")[0].flatpickr({enableTime : true}); }) }, save: function(p){ p.editing = false } }, created(){ self = this posts_loaded = false for(var i = 0;i < this.platforms.length; i++){ (function(index){ self.$http.get('/fan/posts',{params:{platform : self.platforms[index]}}).then(function(resp){ self.platform_posts[self.platforms[index]] = resp.body posts_loaded = true })//Promise of Ajax call }// Closure body )(i)//Closure } this.showTab(0) }, delimiters: ['[[',']]'] })

and my basic html template :

<div class = "panel-body"> <img class = "pull-right responsive" v-bind:src = "p.image"/> <textarea v-if = "p.editing" class = "post-text-input" v-model = "p.text"></textarea> <p class = "post-text" v-if = "!p.editing">[[p.text]]</p> <p class = "post-source" v-if = "p.type == 'article'"> Source : [[post_source(p)]]</p> <p class = "post-time"><b>Scheduled on <i v-if = "!p.editing">[[p.time]] </i></b> <input placeholder="Choose a date and a time" class = "flatpickr dt-input" v-model = "p.time" v-if = "p.editing" /> </p> </div> <div class = "panel-footer clearfix"> <button class = "btn btn-danger">Delete</button> <button class = "btn btn-info pull-right" @click = "edit(p)" v-if = "!p.editing">Edit</button> <button class = "btn btn-success pull-right" @click = "save(p)" v-if = "p.editing">Save</button> </div>

Code explanation:

So, when a tab is clicked, showTab(index) is called where index is the number of tab, if index is 0 then we switched to facebook tab, if it's 1 then we're in the twitter tab, we send an AJAX request to get the posts for that current platform (tab) and fill it in platform_posts[current_platform], we then render them via v-for . All of this is working like a charm .

Second part, when user click on the edit button for a given post, it replace the text paragraph element with a textarea using v-model to keep track of change and update the time paragraph with an input which acts as datetime picker via flatpickr library . Basically this lib can turn any input into a datetime pickr using this line of code :

elemnt.flatpickr({config_options})

Where element is an HTML element . You can notice that I'm using Vue.nextTick, this is to make sure that the input is not hidden anymore (it shouldn't be since p.editing is updated) . All of this work like a charm when I'm on the first tab, the problem is that when I switch the tab it stop working .

Here's a gif I made to show you the error : http://imgur.com/a/QME4P

As you can see, the behaviour is very weird, it works perfectly on the twitter tab and it's weird on the facebook tab .

Categories: Software

Pages