Vuejs

Subscribe to Vuejs feed
most recent 30 from stackoverflow.com 2017-09-14T21:10:11Z
Updated: 7 years 1 week ago

Vuejs unit test - watcher on props

Tue, 2017-08-01 16:12

I'm trying to unit test a watcher on a props in a Vue component. I'm using Karma+Jasmine. But it seems that watchers on props are not triggered in unit test.

Here is a simple component :

export default { name: 'hello', data: function () { return { b: null }; }, props: { a: { type: String, default: null } }, watch: { a(val) { this.b = val; } }, computed: { c() { return this.a + " computed"; } } }

and here is my test :

describe('Hello', () => { const HelloCtor = Vue.extend(Hello); let vm; beforeEach(() => { vm = new HelloCtor({ propsData: { a: "hello" } }).$mount(); }); afterEach(() => { vm.$destroy(); }); it('should watch a and compute c', (done) => { vm.$nextTick(() => { expect(vm.c).toBe("hello computed"); expect(vm.b).toBe("hello"); done(); }); }); });

In the asserts, 'c' is correctly computed but 'b' is always null. If I move 'a' to data everything works perfectly. Note that when I test my app manually in my browser, watchers on props are triggered just like the ones on data variable.

Any ideas on how to test it ?

Categories: Software

Vue.js not all transition group children are animating

Tue, 2017-08-01 15:43

This is the transition group that I am using

<article class="hotel-row" v-for="hotel in paginatedHotels" :key="hotel.hotelid"> <search-hotel :hotel="hotel"></search-hotel> </article>

Vue will throw an error if I do not key the children:

[Vue warn]: children must be keyed:

No problem I add my unique hotelid to make sure Vue can make a distinction between elements.

I have a list of 25 hotels and the problem is that when I keyed my child elements that the elements that were in my first 25 results and also in the results after updating my list of hotels do not animate.

Vue apparently tracks these now with the :key and does not find it needed to animate these children.

I am guessing this happens because there are already part of the list so why animate them again? My list can totally re-order though so I would prefer to always have all items animate.

I can clearly see that the transition classes are not added to elements that are the same before and after my transition.

How can I make sure all elements are animated though?

Categories: Software

Could not resolve view with name 'HelloWorld' in servlet with name 'dispatcherServlet'

Tue, 2017-08-01 15:40

I started study Spring Boot just.

I want to display html page .

But It doesn't work.

If I change HelloWorld.html to HelloWorld.ftl . I can display ftl page ,but the vue.js is not resolve file .

below my Spring boot configure File and Controller.

application

spring.resources.chain.strategy.content.enabled=true spring.resources.chain.strategy.content.paths=/** spring.mvc.view.prefix=/ spring.mvc.view.suffix=.html spring.mvc.static-path-pattern=/**

Resources

static/js/vue.js

tempates/HelloWorld.html

Controller

@Controller public class HelloController { @RequestMapping("/hello") public String hello(){ return "HelloWorld"; } }
Categories: Software

How to scroll to specific data value in Vue?

Tue, 2017-08-01 15:10

I have simple table in Vue:

<tbody> <tr v-for="(item, index) in items"> <td> ... </td> </tr> </tbody>

The items are dynamically adding via unshift. The main thing is that I need to navigate through table via up, down keys so I did it like this:

jQuery(document).keydown((e) => { const which = e.which; if ([38, 40].indexOf(which) != -1) { e.preventDefault(); if (this.active_index == null) { this.active_index = 0; } else { if (e.which == 38) { // up this.active_index--; } else { // down this.active_index++; } } console.log(this.items[this.active_index]) } });

Is it possible somehow to get this.items[this.active_index] element or its position to scroll to it.

Categories: Software

How to prevent/stop propagation of default event (click) in directive (vue 2.x)

Tue, 2017-08-01 15:02
Vue.directive('login-to-click', { bind (el) { const clickHandler = (event) => { event.preventDefault() event.stopImmediatePropagation() alert('click') } el.addEventListener('click', clickHandler, true) } })

usage

<button @click="handleClick" v-login-to-click>CLICK</button>

handleClick is always triggered. How I can prevent that from directive? Tried with/without addEventListener "capture" flag without any luck.

Categories: Software

Change image source (twice) when src does not exist

Tue, 2017-08-01 14:34

I just started using Vue in the front-end of my website. In one of my Vue-components I want an image with a certain path:

<img src="path/example/with/vue/var">

Now, this is what I want to do:

  • Check if the file in "path/example/with/vue/var" exists
  • If not: Change the src to "another/path/with/vue/var"
  • Check if "another/path/with/vue/var" exist
  • If not: Change the src to "default/path"

I already tried to use onerror with a function inside of it. But the problem is I'm loading 100+ objects with a couple of images for each object. If I just check if the file exists the normal way(through ajax or with a XMLHttpRequest), the performance is completely gone. All objects are loaded through a JSON file.

I hope you guys understand the question. Thanks!

Categories: Software

how to use listeners in vue.js for events like scroll and windows resizing

Tue, 2017-08-01 14:29

Hello i am learning vuejs and was converting one of my projects into vuejs i wanted to know that i can write my custom functions in methods and call those in mounted hook i wanted to know how do i use listeners in vuejs.

also can i used my jquery by importing in vue project

The event listener documentation on vue website states only v-on and click example but no examples are for windows listeners

jQuery(document).ready(function(){ //cache DOM elements var mainContent = $('.cd-main-content'), header = $('.cd-main-header'), sidebar = $('.cd-side-nav'), sidebarTrigger = $('.cd-nav-trigger'), topNavigation = $('.cd-top-nav'), searchForm = $('.cd-search'), accountInfo = $('.account'); //on resize, move search and top nav position according to window width var resizing = false; moveNavigation(); $(window).on('resize', function(){ if( !resizing ) { (!window.requestAnimationFrame) ? setTimeout(moveNavigation, 300) : window.requestAnimationFrame(moveNavigation); resizing = true; } }); //on window scrolling - fix sidebar nav var scrolling = false; checkScrollbarPosition(); $(window).on('scroll', function(){ if( !scrolling ) { (!window.requestAnimationFrame) ? setTimeout(checkScrollbarPosition, 300) : window.requestAnimationFrame(checkScrollbarPosition); scrolling = true; } }); //mobile only - open sidebar when user clicks the hamburger menu sidebarTrigger.on('click', function(event){ event.preventDefault(); $([sidebar, sidebarTrigger]).toggleClass('nav-is-visible'); }); //click on item and show submenu $('.has-children > a').on('click', function(event){ var mq = checkMQ(), selectedItem = $(this); if( mq == 'mobile' || mq == 'tablet' ) { event.preventDefault(); if( selectedItem.parent('li').hasClass('selected')) { selectedItem.parent('li').removeClass('selected'); } else { sidebar.find('.has-children.selected').removeClass('selected'); accountInfo.removeClass('selected'); selectedItem.parent('li').addClass('selected'); } } }); //click on account and show submenu - desktop version only accountInfo.children('a').on('click', function(event){ var mq = checkMQ(), selectedItem = $(this); if( mq == 'desktop') { event.preventDefault(); accountInfo.toggleClass('selected'); sidebar.find('.has-children.selected').removeClass('selected'); } }); $(document).on('click', function(event){ if( !$(event.target).is('.has-children a') ) { sidebar.find('.has-children.selected').removeClass('selected'); accountInfo.removeClass('selected'); } }); //on desktop - differentiate between a user trying to hover over a dropdown item vs trying to navigate into a submenu's contents sidebar.children('ul').menuAim({ activate: function(row) { $(row).addClass('hover'); }, deactivate: function(row) { $(row).removeClass('hover'); }, exitMenu: function() { sidebar.find('.hover').removeClass('hover'); return true; }, submenuSelector: ".has-children", }); function checkMQ() { //check if mobile or desktop device return window.getComputedStyle(document.querySelector('.cd-main-content'), '::before').getPropertyValue('content').replace(/'/g, "").replace(/"/g, ""); } function moveNavigation(){ var mq = checkMQ(); if ( mq == 'mobile' && topNavigation.parents('.cd-side-nav').length == 0 ) { detachElements(); topNavigation.appendTo(sidebar); searchForm.removeClass('is-hidden').prependTo(sidebar); } else if ( ( mq == 'tablet' || mq == 'desktop') && topNavigation.parents('.cd-side-nav').length > 0 ) { detachElements(); searchForm.insertAfter(header.find('.cd-logo')); topNavigation.appendTo(header.find('.cd-nav')); } checkSelected(mq); resizing = false; } function detachElements() { topNavigation.detach(); searchForm.detach(); } function checkSelected(mq) { //on desktop, remove selected class from items selected on mobile/tablet version if( mq == 'desktop' ) $('.has-children.selected').removeClass('selected'); } function checkScrollbarPosition() { var mq = checkMQ(); if( mq != 'mobile' ) { var sidebarHeight = sidebar.outerHeight(), windowHeight = $(window).height(), mainContentHeight = mainContent.outerHeight(), scrollTop = $(window).scrollTop(); ( ( scrollTop + windowHeight > sidebarHeight ) && ( mainContentHeight - sidebarHeight != 0 ) ) ? sidebar.addClass('is-fixed').css('bottom', 0) : sidebar.removeClass('is-fixed').attr('style', ''); } scrolling = false; } });
Categories: Software

The width of columns in a table change when a row of input boxes is added dinamically

Tue, 2017-08-01 14:25

The table before the row with input-boxes is shown As you see in the image above, there is a table that contains on the first row, a button for showing/hiding the row that contains input-boxes like in the image below.

The table where the row with input boxes is shown The problem is that the width of the columns is changed when the row that contains input-boxes is displayed. (It can be seen from the images the difference of width's columns, before and after)
And the width of the input-boxes is set to 100%. Also the padding and border are not changed, only the width of td. So the question is, how can I mentain the same width of the columns, without setting a fixed width, like in the code below?

td { width: 50px;}

And also adding white-space: nowrap doesn't work!

Here is the part of the code for showing the row with the input-boxes.

<tr v-if="showFilters"> <td v-for="key in filterKeys" v-if="key.visible"> <div class="input-group"> <pf-text-field v-model="key.value" tooltip="Filter"> </pf-text-field> </div> </td> </tr>
Categories: Software

Vue 2 - vuex mapGetters and pass params

Tue, 2017-08-01 14:18

Is it possible to pass params with mapGetters?

I have this in main Vue instance:

computed: { filterAuthors() { return this.$store.getters.filterAuthors(this.search.toLowerCase()); } }

this.search is bind to the input field via v-model="search=, and in my Vuex instance I have this getters:

getters: { filterAuthors: (state) => (search) => { return state.authors.filter((author) => { return author.name.toLowerCase().indexOf(search) >= 0; }) } },

This one is working fine, but I am trying to find a way (if it is possible) to use mapGetters and to pass the argument. Can this be done?

Categories: Software

align content with bootstrap strange behaviour

Tue, 2017-08-01 13:52

I am working with vuejs and bootstrap so i am calling different components and attach them inside my html dynamicly.

My problem is i don't get the desirable effect, at the moment i have this:

image

the section title gives soo much space realted to the input and i don't know why, the section is a diferent component and the data at the bottom gets loaded dynamicly depending on the selectbox choice.

the rows columns and cells are a horizontal form but it occupy all the widht of my row, i want the inputs to be lower and the button at center a little bigger, i can't set it like i want if i try for example to increase button it will not be at center anymore.

So here is my code:

<template> <div class="container"> <div class="row"> <div> <h1 class="text-center">Document Creation</h1> </div> <div class="col-md-4"> <div class="row"> <div class="col-md-6"> </div> <div class="col-md-6"> </div> </div> </div> <div class="col-md-8 margin-above"> <div class="form-group"> <label class="control-label col-sm-2">Section</label> <div class="col-sm-6"> <select class="form-control" v-model="currentView"> <option v-for="(item,index) in sections" :value="item.key">{{item.text}}</option> </select> </div> </div> </div> </div> <!-- Here we load the diferent sections based on the selection choice --> <component v-bind:is="currentView"> <!-- component changes when vm.currentView changes! --> </component> </div> </template>

inside the component the other component that has the rows and cells and columns get loaded like this:

<template> <div class="row"> <div class="col-md-offset-4"> <form class="form-inline margin-above"> <div class="form-group"> <label for="rows">rows:</label> <input type="number" min="1" value="1" class="form-control" id="rows"> </div> <div class="form-group"> <label for="columns">columns:</label> <input type="number" min="1" value="1" class="form-control" id="cols"> </div> <div class="form-group"> <label for="cells">cells:</label> <input type="number" min="1" value="1" class="form-control" id="cols"> </div> <div class="text-center"> <button type="submit" class="btn btn-success margin-above2">Add Table</button> </div> </form> </div> </div> </template>

please i need some help trying to display it correctly . Thanks

Categories: Software

Saga alternative for Vue

Tue, 2017-08-01 13:13

I finished learning Vue.js, it has had almost all I wanted from it! But I can't find something similar to redux-saga. redux-saga is very great tool, and it would be nice to have something like this.

Can someone propose alternative library, or share experience how to manage big projects with complex data-flow without redux-saga.

Categories: Software

Pass data from one component to all with $emit without using @click in VueJS

Tue, 2017-08-01 12:03

Trying to learn vuejs I got to the question how to pass any data from one component to all, using $emit but without using any @click. It is possible some how that the data to be just available and grab it any time, without using the click?

Let's say we have this example with normal @click and $emit.

main.js

export const eventBus = new Vue()

Hello.vue

<template> <div> <h2>This is Hello component</h2> <button @click="emitGlobalClickEvent()">Click me</button> </div> </template> <script> import { eventBus } from '../main' export default { data () { return { msg: 'Welcome to Your Vue.js App' } }, methods: { emitGlobalClickEvent () { eventBus.$emit('messageSelected', this.msg) } } } </script>

User.vue

<template> <div> <h2>This is User component</h2> <user-one></user-one> </div> </template> <script> import { eventBus } from '../main' import UserOne from './UserOne.vue' export default { created () { eventBus.$on('messageSelected', msg => { console.log(msg) }) }, components: { UserOne } } </script>

UserOne.vue

<template> <div> <h3>We are in UserOne component</h3> </div> </template> <script> import { eventBus } from '../main' export default { created () { eventBus.$on('messageSelected', msg => { console.log('From UserOne message !!!') }) } } </script>

I want to get this message : Welcome to Your Vue.js App from Hello.vue in all components, but without @click, if is possible.

Categories: Software

Webix not working with Vue2

Tue, 2017-08-01 11:40

I am adding some Vue2 components to an existing page that uses webix, but that is breaking my webix components.

If I comment this line out , webix works as expected. When app-provider-ui.js is included on the page, webix datatables render, but nothing happens when I click on them.

I use Laravel 5.4, Vue2, and webpack. The Vue instance is mounted on #provider-js-app

Thanks.

<!DOCTYPE html> <html lang="en"> <head> <link href="{{ asset('/css/stylesheet.css') }}" rel="stylesheet"> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script> <script src="{{ asset('/webix/codebase/webix.js') }}" type="text/javascript"></script> </head> <body> <div id="provider-js-app"> @yield('content') <open-modal></open-modal> <notifications></notifications> </div> @include('partials.footer') <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> <script src="{{ asset('/js/bootstrap-select.min.js') }}"></script> <script src="{{ asset('/js/typeahead.bundle.js') }}"></script> <script src="{{asset('/js/bootstrap.min.js')}}"></script> <script src="{{asset('/js/DateTimePicker.min.js')}}"></script> <script src="{{asset('js/app-provider-ui.js')}}"></script> </body> </html>
Categories: Software

vue js in bootstrap navbar

Tue, 2017-08-01 11:33

i am implementing vue js in bootstrap html template... problem i am facing is in navbar..

my code is

<router-link tag="li" to="#"> <a><i class="fa fa-book" aria-hidden="true"></i> <span class="nav-label">Syllabus</span><span class="fa arrow"></span></a> <ul class="nav nav-second-level collapse"> <router-link tag="li" to="/syllabus"> <a> Syllabus</a> </router-link> <router-link tag="li" to="/syllabus/topic"> <a>Syllabus Topic</a> </router-link> </ul> </router-link>

i have also tried using

<li> <a><i class="fa fa-book" aria-hidden="true"></i> <span class="nav-label">Syllabus</span><span class="fa arrow"></span></a> <ul class="nav nav-second-level collapse"> <router-link tag="li" to="/syllabus"> <a> Syllabus 1</a> </router-link> <router-link tag="li" to="/syllabus/topic"> <a>Syllabus Topic</a> </router-link> </ul> </li>

but the problem is when i am reloading the page the menu collapse and expands normally as it should work but when i am clicking on a a sub menu for instance "syllabus1" the page redirects to syllabus but the menu freezes and does not any longer collapse or expands...then again on reloading the menu starts working fine

please help me with this... thanks in advance... please provide an example in jsfiddle if possible... thankx..

Categories: Software

Vue 2 add class active through exploring list

Tue, 2017-08-01 11:15

i have problem with input and lists, I would like to go through from input to list element below and add class 'active' to current li element

<div class="control"> <label class="label">Input Test</label> <input type="text" class="input" @keydown="keyHandler"> <ul> <li v-for="suggestion in suggestions" v-bind:class="{active}">{{suggestion.message}}</li> </ul> </div> methods : { keyHandler(e){ if(e.keyCode === 38){ e.preventDefault(); console.log('arrow up') this.currentKey = e.key } else if(e.keyCode === 40){ e.preventDefault(); console.log('arrow down') this.currentKey = e.key } } }

here is fiddle: https://jsfiddle.net/o8fwf0gh/13/

I would be grateful for help

Categories: Software

Passing data from parent to be rendered on component, data passage failure

Tue, 2017-08-01 11:10

I am trying to pass a first and last name to a child component to render as a custom element. Should be simple. But I am not able to link up my props for some reason. Here is the relevant parent code...

<div class="panel-body"> <full-name :userData.firstname="firstname" :userData.lastname="lastname"></full-name> </div> <script> import toggleSwitch from './components/toggleSwitch.vue'; export default { data () { return{ userData: { firstname: '', lastname: '' } } }, components: { 'fullName': fullName } } </script>

As you can see I call the element and pass it my two data props. Once there I simply output my data via string interpolation, and... nothing shows. Here is my output component

<template> <div> <p>{{firstname}} {{lastname}}</p> </div> </template> <script> export default{ props: ['firstname', 'lastname'] } </script>

Am I missing something obvious? Thanks in advance.

Categories: Software

Vue.js raw HTML within attribute

Tue, 2017-08-01 10:53

Is there a way to output raw HTML to a tags attributes rather than content?

Example:

<input :placeholder="data.raw-html-message"/> ... data.raw-html-message = "some text&hellip;"

v-html seems to only output it to the innerHTML of the tag and the triple curly braces have been removed in version 2.

Currently with a standard v-bind the output is:

<input placeholder="Message&hellip;" />

and the HTML entity is not interpreted when displayed in the browser.

Categories: Software

vue-router same route with different param

Tue, 2017-08-01 10:03

I am on the /entry/12 route. On the same component I would like to push /entry/13 when user clicks the next button.

Code is like :

//e is the next page number. this.$router.push({ name: 'Entries', params: { pageNum: e }});

I get below error:

enter image description here

If i try different route that works.

Categories: Software

VueJS - v-if and v-show don't work properly

Tue, 2017-08-01 09:22

I have this structure inside Vue DIV:

<div class="row"> <div class="well chart-container"> <div id="chart" v-if="chartShown"></div> <h1 v-if="textShown">{{staticPropertyValue}}</h1> </div> </div>

In my application I'd like to be able to display chart div OR h1 tag. Here's a part of my javaScript:

app.textShown = false; app.chartShown = true; if (data.length == 0) { MG.data_graphic({ title: "Missing Data", description: "", error: 'No data', chart_type: 'missing-data', missing_text: 'There is no data', target: '#chart', full_width: true, height: 600 }); return; }; if (data.length == 1) { app.staticPropertyValue = data[0].value; app.chartShown = false; app.textShown = true; return; } console.log('DRAWING GRAPH'); console.log(document.getElementById('chart')); MG.data_graphic({ title: "Fetched data", description: "", data: data, full_width: true, height: 600, target: '#chart', x_accessor: 'time', y_accessor: 'value' });

So, depending on data.length property, the chart is shown or h1 tag is shown. The problem appears, when I first time call above code and display h1 tag (because data.length == 1) and then next time I call it with date.length > 1 (chart should appear). I get error:

The specified target element "#chart" could not be found in the page. The chart will not be rendered.

It is from the library that I'm using for drawing charts - metricsgraphics.js. So I console logged the result of

document.getElementById('chart')

and it was null. So it means that although i switch chartShown to true, it's not done fast enough. How can I fix this?

I also tried using v-show instead of v-if - didn't work well - I had some errors about the width of some elements being NaN.

Categories: Software

Vue router async route guard progress

Tue, 2017-08-01 09:19

I'm doing async work in my router's navigation guard:

router.beforeEach((to, from, next) => { somethingAsync().done(next) })

Does the router expose anything to tell me that it's currently "loading"? Or do I need to keep track of it myself? Right now the content will pop up in<router-view></router-view> once the async work is completed. My current solution is to keep track of active work in my Vuex store and show a loading element next to the router view.

Categories: Software

Pages